제목: 정렬 알고리즘에서 시간 복잡도 O(n)을 달성할 수 있을까?
서론
이전 포스팅에서 Merge Sort에 대해 다룬 적이 있다. Merge sort는 O(n log n) 시간 복잡도를 갖는 효율적인 알고리즘이었다. 그러나 Merge Sort는 비교 기반 정렬 알고리즘으로, 입력 데이터의 크기 n에 대해 최소 Ω(n log n) 시간이 소요됨이 증명되었다. 이는 다음의 Decision tree를 통해 알 수 있다.
Comparison Based Sorting
![]() |
decision tree |
![]() |
runtime analysis |
즉, 그림과 같은 양쪽으로 균일한 tree의 경우가 comparison based sorting 중 가장 빠른 경우이다. Tree의 depth, 즉 longest path가 log(n!)이므로 이 알고리즘은 최소한 Ω(log(n!))의 실행 시간을 갖는다. 그리고 이는 n log(n/e)로 근사되어 Ω(n log(n))의 runtime을 갖게 된다.
Linear Time Sorting
선형 시간 정렬 알고리즘은 특정 조건을 만족하는 입력 데이터에 대해 O(n) 시간 복잡도를 달성하는 알고리즘이다. 즉, 입력 데이터의 크기에 비례하는 시간 안에 정렬을 완료할 수 있다. 이러한 알고리즘들은 비교 기반 정렬 알고리즘과 달리, 데이터의 값 자체를 이용하여 정렬을 수행한다.
Counting Sort
Counting Sort는 입력 배열의 각 요소가 0과 k 사이의 정수라는 가정 하에 동작한다.
Counting sort code
코드를 살펴보면, counts에 특정값의 개수를 세고 개수만큼 result에 집어넣음으로써 구현된다.counts
![]() |
result |
Counting sort는 k가 충분히 작을 때 매우 효율적이, 시간 복잡도는 O(n+k)이다. 하지만 k가 매우 큰 경우, Counting Sort는 비효율적이 된다. 예를 들어, 입력 배열의 요소가 0과 1,000,000 사이의 정수라면, Counting Sort는 O(n+1,000,000) 시간이 소요되어 O(n log n) 알고리즘보다 느릴 수 있다.
그리고 stable한 정렬 알고리즘으로, 입력 배열에서 같은 값을 갖는 요소들의 상대적인 순서가 정렬된 배열에서도 유지된다.
Bucket Sort
Bucket Sort는 입력 배열의 요소들이 균등 분포를 따른다는 가정 하에 동작한다.
![]() |
Bucket sort code |
코드를 통해 Bucket sort는 Bucket들로 분할하고, 분할된 요소들을 정렬함으로써 수행됨을 알 수 있다.
Bucket |
이때 k ≤ Bucket 수라면 저장할 index가 충분하므로 counting sort를 이용하여 정렬할 수 있고, k > Bucket 수라면 다른 stable sort를 이용해서 정렬한다.
Bucket sort는 '분할'의 특성에 의해 k가 커도 상관없지만, 입력 데이터가 균등 분포를 따르지 않으면 성능이 저하될 수 있다. 만약 입력 데이터가 균등 분포를 따르지 않는다면, 특정 버킷에 많은 요소가 몰릴 수 있다. 이 경우 해당 버킷 내에서 정렬하는 데 O(n log n) 시간이 소요될 수 있으며, 전체적인 성능이 저하된다.
정리하면 최악의 경우 시간 복잡도는 O(n^2)이지만, 평균적으로 O(n) 시간 복잡도를 갖는다.
Radix Sort
Radix Sort는 입력 배열의 요소들이 d자리 정수라는 가정 하에 동작한다.
이 알고리즘은 각 자릿수에 대해 오름차순으로 stable한 정렬 알고리즘을 반복적으로 적용하여 정렬을 수행한다.
Radix sort의 시간 복잡도는 O(d(n+k))이며, d가 작고 k가 n에 비해 크지 않을 때 효율적이다.
Radix Sort에서 stable한 정렬 알고리즘을 사용하는 이유는 각 자릿수를 정렬할 때 이전 자릿수의 정렬 순서를 유지하기 위해서이다. 만약 stable하지 않은 정렬 알고리즘을 사용한다면, 이전 자릿수에서 정렬된 순서가 섞여 최종 결과가 잘못될 수 있다.
결론
선형 시간 정렬 알고리즘은 특정 조건을 만족하는 입력 데이터에 대해 매우 효율적인 정렬 방법을 제공한다. Counting Sort는 k가 작을 때, Bucket Sort는 데이터가 균등 분포를 따를 때, Radix Sort는 d가 작을 때 효과적이다. 반면, 비교 기반 정렬 알고리즘은 입력 데이터에 대한 제약이 없지만, 최소 Ω(n log n) 시간이 소요된다. 따라서 각 알고리즘의 특징을 정확하게 이해하고, 입력 데이터의 특성에 맞는 알고리즘을 선택하는 것이 중요하다.
추천글 :
[알고리즘] merge sort algorithm analysis
(https://hyeonb.blogspot.com/2024/09/merge-sort-algorithm-analysis.html)
[알고리즘] Algorithmic analysis - runtime with asymptotic analysis
(https://hyeonb.blogspot.com/2024/09/algorithmic-analysis-runtime-with.html)