1. 알고리즘별 정의, 장점, 단점 정리
종류 | 정의 | 장점 | 단점 | 이용 |
버블 정렬(Bubble Sort) | 첫 번째 원소부터 인접한 원소끼리 계속 자리를 교환하면 맨 끝까지 정렬하는 방식 | 구현이 간단 코드가 직관 |
정렬 시간이 오래 걸림 | 이미 정렬된 데이터를 정렬 시에 빠르다(반대로 역순 배열은 가장 느림) |
선택 정렬(Selection Sort) | 최소 값을 찾고 그 값을 맨 앞에 위치한 값과 교체하는 방식(반복) | 구현이 간단 비교하는 횟수에 비해 교환이 적게 일어남 버블 정렬보다 빠름 |
정렬 시간이 오래 걸림 | 많은 교환이 일어나야 하는 자료 상태에서 비교적 효율적(역순 정렬) 이미 정렬된 상태에서 소수의 자료가 추가됨으로 재정렬할 시 최악 |
삽입 정렬(Insertion Sort) | 자료 배열의 모든 요소를 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여 자신위 위치를 찾아 삽입하는 방식 | 최선의 경우 O(N)으로 정렬 가능 | 최악의 경우 O(N^2)이 걸림 | 다른 정렬 알고리즘의 일부로 쓰임 이미 정렬된 경우 아주 최고의 정렬 알고리즘(탐색을 제외한 오버헤드가 매우 적음) |
합병 정렬(Merge Sort) | 작은 단위로 잘게 쪼개어 작은 단위부터 정렬해서 정렬된 단위들을 계속 병합해가면서 정렬하는 방식 | 항상 O(NlogN)으로 일정한 속도로 정렬 | 추가적인 메모리 공간 필요(임시 배열에 원본 맵을 계속해서 옮겨주면서 정렬하는 방법) | 순차적인 비교로 정렬하기에 LinkedList의 정렬에 사용하면 효율적 크기가 큰 레코드 정렬 시 효율적 |
퀵 정렬(Quick Sort) | Pivot을 정하여 이 축의 값보다 작은 값은 왼쪽에 큰 값은 오른쪽으로 위치시킨뒤 왼쪽과 오른쪽의 수들을 다시 각각의 축으로 나누어져 축 값이 가장 작은 값이 될 때까지 정렬 | 평균 실행시간 O(NlogN)으로 빠른 편 | Pivot에 따라 성능 차이가 심함 최악의 경우 O(N^2)이 걸림 |
순차 접근이 아닌 임의 접근이기에 LinkedList를 퀵 정렬에 사용하면 성능이 좋지 않다 |
힙 정렬(Heap Sort) | 최대 힙을 만들고 루트 노드를 던지고 마지막 노드를 루트 노드 위치에 넣고 다시 최대 힙 만들기를 반복 | 항상 O(NlogN)으로 빠른 편 | 다른 O(NlogN)의 정렬법보다 오래 걸림 |
가장 크거나 가장 작은 값을 구할 때 최대 K만큼 떨어진 요소들을 구할 때 : 삽입 정렬을 개선 |
쉘 정렬(Shell Sort) | 삽입정렬의 개념을 확대하여 일반화한 정렬방법 | O(NlogN)의 정렬법보다 빠름 | 설정 간격에 따라 성능 차이가 심함 | 삽입 정렬을 보안한 알고리즘으로 삽입 정렬 시 삽입되어야할 위치가 현재 위치에서 상당히 멀리 떨이진 곳에 정렬을 해야만 하는 경우 쉘 정렬 사용 |
기수 정렬(Radix Sort) | 데이터의 비교를 통한 정렬이 아닌 분산 정렬을 이용한 정렬 방법으로 자릿수가 있는 데이터(정수, 문자열 등)에만 사용 가능 | O(N) 속도로 굉장히 빨리 정렬 가능 | '버킷'이라는 추가적인 메모리가 할당되어야 한다. 즉, 메모리가 생각보다 많이 소비 데이터 타입이 항상 일정해야함 구현을 위한 조건이 많이 붙음 |
자릿수가 있는 데이터를 정렬할 경우 |
계수 정렬(Counting Sort) | 비교하지 않는 정렬로 정렬하기 위한 요소들이 몇 개씩 있는지 세어서 적절한 위치에 선형 시간에 정렬하는 방법 | 적은 개수의 숫자를 정렬할 때 빠름 | 추가적인 메모리(숫자 개수를 저장할 공간, 결과를 저장할 공간)가 필요 가장 큰 숫자에 영향을 받는다는 점 |
특정 범위내에서 반복되는 정수인 많은 데이터의 경우에 효율적 (만약 데이터의 특성을 파악하기 어렵다면 퀵 정렬을 이용하는 것이 유리) |
2. 알고리즘별 시간복잡도 및 공간 복잡도
종류 | 평균 | 최선 | 최악 | 공간 복잡도 |
버블 정렬(Bubble Sort) | O(N^2) | O(N^2) | O(N^2) | O(N^2) |
선택 정렬(Selection Sort) | O(N^2) | O(N^2) | O(N^2) | O(N) |
삽입 정렬(Insertion Sort) | O(N^2) | O(N) | O(N^2) | O(N^2) |
합병 정렬(Merge Sort) | O(NlogN) | O(NlogN) | O(NlogN) | O(NlogN) |
퀵 정렬(Quick Sort) | O(NlogN) | O(NlogN) | O(N^2) | O(NlogN) |
힙 정렬(Heap Sort) | O(NlogN) | O(NlogN) | O(NlogN) | O(NlogN) |
쉘 정렬(Shell Sort) | O(N^1.25) | O(N^1.25) | O(N^1.25) | O(N) |
기수 정렬(Radix Sort) | O(dN) / d는 최대값의 자릿수 | O(dN) | O(dN) | O(N) |
계수 정렬(Counting Sort) | O(N+k) | O(N+k) | O(N+k) | O(K) / K는 K 크기만큼의 배열을 만들어야 한다는 뜻 |
ETC
- 추가적인 메모리 할당이 불가능한 경우 병합 vs 큌 : 데이터가 최악인 것만 본다면 퀵 보다 병합 정렬이 훨씬 빠르지만 추가 메모리 할당이 없다면 병합 정렬은 사용 불가이기에 퀵을 써야한다
- 안정 정렬 : 중복된 값을 입력 순서와 동일하게 정렬하는 특성 ex) 삽입 정렬, 버블 정렬, 합병 정렬, 계수 정렬
- 불안정 정렬 : 중복된 값이 입력 순서와 동일하지 않게 정렬되는 특성 ex) 선택 정렬, 퀵 정렬, 힙 정렬
- 기본으로 탑재 되어있는 언어의 라이브러리 중 정렬은 시간 복잡도가 보통 NlogN으로 잘 판단하여 사용할 것.