개발자의 서재
자료구조, 알고리즘, 시간복잡도 간단정리 본문
<자료구조, 알고리즘, 시간복잡도>
* 자료구조란?
자료구조란 데이터를 표현하거나 저장하는 방법이다.
1. 단순구조
기본자료형 (2진수, 정수,실수, 문자, 문자열 )
2. 파일구조
순차파일, 색인파일, 직접파일
3. 선형구조 = 데이터간 관계가 1:!
리스트, 연결리스트, 데크, 스택, 큐
4. 비선형구조 = 데이터간 관계가 1:N / N:M
트리 - 일반트리, 이진트리
그래프 - 방향그래프, 무방향 그래프
* 알고리즘이란?
자료구조가 데이터를 표현하거나 저장하는 방법이라면
알고리즘은 데이터를 이용하여 문제를 해결하기 위한 절차나 방법.
* 좋은 알고리즘을 위한 5가지 조건
1. 입력 - 0개이상의 입력
2. 출력 - 1개 이상의 출력
3. 명확성 - 각 명령어의 의미는 모호하지 않고 명확성
4. 유한성 - 한정된 수의 단계후에는 반드시 종료되어야 한다.
5. 유효성 - 각 명령어들은 실행가능한 연산이어야 한다.
* 알고리즘 표현방법
1. 자연어
2. 순서도
3. 의사코드
4. 프로그래밍 언어
* 시간복잡도 / 공간복잡도
효과적인 알고리즘을 얻기위해 알고리즘의 성능을 분석하고 평가할수 있어야한다.
컴퓨터에서는 시간과 메모리 두 자원이 알고리즘의 효율성을 측정하는 척도가 된다.
알고리즘의 수행시간을 분석한 결과를 "시간 복잡도" 라고 하며, => 명령어의 실행횟수
메모리 사용량을 분석한 결과를 "공간 복잡도" 라고 한다. => 메모리 사용량
효율적인 알고리즘이란 입력값이 커짐에 따라 증가하는 시간의 비율을 최소화한 알고리즘을 구성
void f(int n){
int cnt = 0; //1
int sum = 0; //1
for(int i=0; i<n l i++){
cnt++; //n
sum += i; //n
}
}
위 알고리즘의 시간복잡도함수는 f(n) = 2n + 2 이다.
n은 입력개수를 뜻하며, n이 증가하면 그에 비례하여 시간도 증가한다.
* big-o 표기법
알고리즘의 시간복잡도와 공간복잡도를 표현하는 대표적인 방법에는 big-o 표기법이 있다.
big-o 표기법은 알고리즘 실행에 있어 최악의 경우를 나타낸다.
아무리 최악이라도 이정도의 성능은 보장! 이라는 뜻.
오메가 표기법 -> 알고리즘 최상의 실행시간
세타표기법 -> 알고리즘 평균 실행시간
즉, 시간또는 공간의 상한선을 두는 것이다.
* 효율적인 순서
O(1)
상수형
입력값이 아무리커도 실행시간 일정, 최고의 알고리즘
O(log n)
로그형
실행시간은 입력값에 영향을 받지만 큰 n에 대해서도 매우빠르다. 이진검색 알고리즘의 수행시간
업/다운 게임. bfs 알고리즘이 대표적
O(n)
선형
입력값에 비례해서 수행시간이 증가한다.
range길이가 n개인 for문이 대표적
O(n*log n)
선형로그형
대부분의 효율좋은 정렬알고리즘의 수행시간.
비교 기간 정렬알고리즘은 아무리 좋은 알고리즘도 O(n*log n) 보다 빠를 수 없다.
O(n^2)
제곱시간(2차형)
버블정렬같은 비효율적인 알고리즘의 수행시간
이중for문
O(2^n)
지수형
재귀로 구현하는 피보나치 수열은 O(2^n) 의 대표적인 알고리즘이다. 시간이 기하급수적으로 늘어난다.
O(n!)
팩토리얼형
* 최선, 평균, 최악의 경우
일반적으로 알고리즘을 평가할때 최선의 경우와 최악의 경우를따진다.
배열내의 어떠한 x 값을 찾을때 첫번째 index부터 순차적으로 찾는 알고리즘이 있다.
최선의 경우 첫번째 index에 x값이 위치하여 한번에 찾을 수 있거나
최악의 경우 index 마지막에 x값이 위치하여 배열의크기 (n) 만큼 전부 찾아야 할것이다.
해당 알고리즘의 최선의 경우에는 O(1), 최악의 경우에는 O(n) 이라고 말할수 있을 것이다.
* 자바 컬렉션 자료구조별 시간 복잡도
add() | remove() | get() | contains() | |
ArrayList | O(1) | O(n) | O(1) | O(n) |
LinkedList | O(1) | O(1) | O(n) | O(n) |
*리스트는 remove와 get에서 어레이리스트와 연결리스트간에 차이가 있으며
contains는 모두 O(n)이다.
push() | pop() | peek() | search() | |
Stack | O(1) | O(1) | O(1) | O(n) |
*스택은 검색만 o(n), pop,peak는 o(1) 이다.
add() | contains() | next() | |
HashSet | O(1) | O(1) | O(h/n) |
LinkedHashSet | O(1) | O(1) | O(1) |
TreeSet | O(logn) | O(logn) | O(logn) |
HashSet은 contains() 시간복잡도가 O(1)로서 List 보다 검색이 더 효율적이다.
TreeSet(이진트리)는 예외로 모두 O(logn)이다.
offer() | peak() | poll() | size() | |
PriorityQueue | O(logn) | O(1) | O(logn) | O(1) |
get() | contains() | |
HashMap | O(1) | O(1) |
LinkedHashMap | O(1) | O(1) |
TreeMap | O(logn) | O(logn) |
*Map도 contains() 검색효율이좋다.
treemap은 O(logn) 이다.
<java 컬렉션 프레임워크>
list - 순서가 있는 데이터의 집합. 중복허용. 리스트, 스택, 큐
set - 순서가 없고 중복을 비허용
map - key, value 쌍. 순서없음. 키는 중복비허용, 밸류는 중복 허용
링크드 리스트는 자신과 연결된 다음요소의 주소값으로 구성되어 있음.
이중연결리스트 - 이전요소에 대한 참조된 추가버전 (링크드 리스트 단점보완)
별도의 저장공간이 더 필요하다.
어레이리스트 - 검색빠름, 추가삭제(느림) - 순차적인 추가삭제는 더 빠름.
링크드리스트 - 검색느림, 추가삭제(빠름)
스택
lifo 방식
큐
fifo 방식
tree셋은 이진검색트리라는 자료구조를 가진 컬렉션
이진검색트리는 정렬, 검색, 법위검색에 높은성능을 보이는 자료구조.
각 노드에 최대 2개의 노드를 연결할 수 있으며,
루트라고 불리는 하나의 노드에서 시작하여 확장가능.
부모노드의 왼쪽에는 부모노드보다 작은값, 오른쪽에는 큰값 저장.
해시맵과 해시테이블.
key/value
1. 검색하고자 하는 키로 해시함수를 호출한다.
2. 해시함수의 계산결과인 해시코드를 이용해서 해당값의 위치 찾음.
1.14 컬렉션 클래스 정리&요약
ArrayList - 배열기반, 데이터의 중간 추가와 삭제에 불리, 순차적인 추가/삭제는 가장 빠름.
임의의 요소에 대한 접근성이 좋음
LinkedList - 연결기반, 데이터의 중간 추가와 삭제에 유리, 임의의 요소에 대한 접근성이 나쁨.
Stack - LIFO 형식의 컬렉션클래스
Queue - FIFO 형식의 컬렉션 클래스
HashSet - 대표적인 set 컬렉션클래스
TreeSet - 이진검색트리형태의 set, 정렬,검색, 범위검색에 좋음
LinkedHashSet - HashSet에 저장순서유지기능을 추가
HashMap - 배열과 연결이 결합된 형태, 추가,삭제,검색,접근성 모두 뛰어남. 검색에는 최고성능
TreeMap - 연결기반, 정렬과 검색(특히 범위검색)에 적합. 검색성능은 HashMap 보다 떨어짐.
LinkedHashMap - HashMap 에 저장순서유지기능을 추가
<정렬 알고리즘>
기본 정렬 알고리즘 요약정리 (선택, 삽입, 버블, 합병, 퀵)
1. 선택정렬
선택정렬은 현재위치에 들어갈 값을 찾아 정렬하는 방식.
최소선택정렬 = 오름차순
최대선택정렬 = 내림차순
1-맨앞 인덱스에서부터 이를 포함한 이후의 배열값중 가장 작은값찾음. > 작은값을 현재 인덱스로 옮김.
2-다음 인덱스부터 위의 과정 반복.
이알고리즘을 n-1개, n-2개....1개 씩 비교를 반복한다.
배열이 어떻게 되어있던 전체 비교를 진행하므로 시간복잡도는 O(n^2) 이다.
시간복잡도는 O(n^2) / 공간복잡도는 하나의배열에서만 하므로 O(n)
2. 삽입정렬
삽입정렬은 현재위치에서 그 이하의 배열들을 비교하여 자신이 들어갈 위치를 찾아
그 위치에 삽입하는 방식이다.
1-삽입정렬은 두번째 인덱스부터 시작한다.
현재 인덱스값은 별도의 삽입변수에 저장해주고 비교인덱스를 현재인덱스-1로 잡는다.
2-삽입변수와 비교인덱스값을 비교한다.
3-삽입변수의 값이 더 작으면 비교인덱스위치를 -1을 하여 비교를 반복한다.
4-삽입변수가 더 크면 비교인덱스 + 1에 삽입변수를 저장한다.
이 정렬알고리즘의 경우 최악의 경우(역으로 정렬되어 있을때) 선택정렬과 마찬가지로 O(n^2) 이지만
이미 정렬되어 있는 경우는 한번밖에 비교를 하지않아 O(n) 이다.
하지만 빅오 표기법에서는 최악을 기준으로 평가하므로 삽입정렬의 시간복잡도는 O(n^2) 이다.
3. 버블정렬
버블정렬을 매번 연속된 두개 인덱스를 비교하여 정렬 하는 방식이다.
1- 두번째 인덱스부터 시작한다. 현재인덱스값과 바로 이전의 인덱스값을 비교한다.
2- 이전 인덱스값이 더 크면 현재 인덱스값과 바꿔준다.
3- 현재 인덱스값이 더 크면 교환하지 않고 다음 두 연속된 배열값을 비교한다.
이 알고리즘은 1부터 비교를 시작하여 n-1개, n-2개... 1개씩 비교를 반복
선택정렬과 마찬가지로 시간복잡도는 O(n^2) 이다.
4. 합병정렬
합병정렬은 분할정복 방식으로 설계된 알고리즘이다.
분할정복은 큰 문제를 반으로 쪼개 문제를 해결하는 방식으로, 분할은 배열의 크기가 1보다 작거나 같을때 까지
반복한다.
입력으로 하나의 배열을 받고, 연산중에 두개의 배열로 계속 쪼개나간뒤, 합치면서 정렬해
최후에는 하나의 정렬을 출력한다.
1-현재배열을 반으로 쪼갠다.
2-배열의 시작위치 + 종료위치 / 2 하여 그위치를 기준으로 다시 나눈다.
3-이를 쪼갠 배열의 크기가 0이거나 1일때까지 반복한다.
4-쪼객 다음 다시 합치기 시작 이때 두 배열의 값을 비교하여 작은값을 앞에, 큰값을 뒤에놓고 붙인다.
5.다시 붙이기시작. 두배열의 앞부분부터 비교하여 작은값을 앞에다 붙이는방식으로 두배열 함칩.
6. 최종적으로 하나의 배열이 될때까지 이 방식으로 합칩.
합병정렬의 시간복잡도는 O(n log n) 이다.
5.퀵 정렬
퀼 정렬또한 분할정복을 이용하여 정렬을 수행하는 알고리즘 이다.
피봇포인트라고하는 기준이 되는 값을 하나 설정하는데 이 값을 기준으로 작은값은 왼쪽. 큰값을 오른쪽으로
옮기는 방식으로 정렬을 진행한다. 이를 반복하여 분햘된 배열의 크기가 1이 되면 배열이 모두 정렬된 것이다.
1-피봇포인트로 잡을 배열의 값을 하나 정한다.
2-비교를 진행하기위한 가장 왼쪽배열의 인덱스를 저장, 가장 오른쪽 배열의 인덱스를 저장.
.... 잘이해가 안됨.
퀵 정렬은 분할과 동시에 정렬을 진행하는 알고리즘이다.
각 정렬은 배열의 크기 n 만큼 비교하며, 이를 총분할깊이인 log n만큼 진행하므로
시간복잡도는 O(n log n) 이다.
다만 퀵정렬에는 최악의 경우가 존재하는데 배열이 이미 정렬되어 있는경우이다.
이 경우 분할이 n 만큼 일어나므로 시간복잡도는 O(n^2) 이다.
이를 방지하기위해 앞서 중간값이나 랜덤값으로 피봇포인트를 정하기도 한다.
최악의 경우 합병정렬보다 느린 알고리즘이지만, 발생하기 쉽지 않은 경우이고,
일반적으로 퀵 정렬이 합병정렬보다 20%이상 빠르다고 한다.
<정리>
정렬 | 최상 | 평균 | 최악 | 최악의 공간복잡도 |
퀵 정렬 | O(nlogn) | O(nlogn) | O(n^2) | O(nlogn) |
병합 정렬 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) |
힙 정렬 | O(n) | O(nlogn) | O(nlogn) | O(n) |
버블 정렬 | O(n) | O(n^2) | O(n^2) | O(1) |
삽입 정렬 | O(n) | O(n^2) | O(n^2) | O(1) |
선택 정렬 | O(n^2) | O(n^2) | O(n^2) | O(1) |
-----------------------------------------------
[Java] Arrays.sort()와 Collections.sort()의 시간복잡도 비교
정렬 방식 시간 복잡도
Arrays.sort()
DualPivotQuicksort(듀얼 피봇 퀵 정렬)
평균 : O(nlog(n)) / 최악 : O(n^2)
Collections.sort()
TimeSort (삽입정렬과 합병정렬을 결합한 정렬)
평균, 최악 : O(nlog(n))
'알고리즘, 코딩테스트' 카테고리의 다른 글
DFS - 깊이우선 탐색 알고리즘 작성 (0) | 2022.02.17 |
---|