CS/알고리즘
[알고리즘] 기타 정렬 알고리즘(계수, 기수, 외부)
초코chip
2024. 9. 29. 17:13
알고리즘 | 최적 시간 | 평균 시간 | 최악 시간 | 제자리 정렬 | 안정 정렬 |
거품 정렬 | O(n) | O(n²) | O(n²) | O | O |
선택 정렬 | O(n²) | O(n²) | O(n²) | O | X |
삽입 정렬 | O(n) | O(n²) | O(n²) | O | O |
퀵 정렬 | O(n log n) | O(n log n) | O(n²) | O | X |
병합 정렬 | O(n log n) | O(n log n) | O(n log n) | X | O |
힙 정렬 | O(n log n) | O(n log n) | O(n log n) | O | X |
기수 정렬 | O(nk) | O(nk) | O(nk) | X | O |
계수 정렬 | O(n + k) | O(n + k) | O(n + k) | X | O |
In-place & Stable Sort
- 제자리 정렬(in-place sorting): 추가적인 메모리 공간을 거의 사용하지 않고, 입력 배열 자체에서 정렬을 수행하는 알고리즘을 의미
- O(1) 또는 O(log n) 정도의 보조 메모리만 사용하며, 기존 데이터를 재배치하는 방식으로 작동
- 안정 정렬(Stable Sort): 동일한 값의 요소들이 정렬 전후의 순서가 바뀌지 않는 정렬 알고리즘을 의미
- 즉, 값이 같은 데이터가 있을 때, 원래의 입력 순서가 보존
계수 정렬(Count Sort)

- 정의: 데이터의 크기를 기준으로 횟수를 세어 정렬하는 알고리즘
- 목적: 범위가 작고 데이터 분포가 균일한 경우에 적합
- 특징:
- 비교 기반 아님: 데이터를 직접 비교하지 않고, 각 값의 빈도를 계산하여 정렬
- 제자리 정렬 아님: 정렬을 위한 추가 공간 필요
- 불안정 정렬: 동일한 값에 대해 초기 순서가 유지되지 않음
자바 코드
int arr[5]; // [5, 4, 3, 2, 1]
int sorted_arr[5];
// 과정 1 - counting 배열의 사이즈를 최대값 5가 담기도록 크게 잡기
int counting[6]; // 단점 : counting 배열의 사이즈의 범위를 가능한 값의 범위만큼 크게 잡아야 하므로, 비효율적이 됨.
// 과정 2 - counting 배열의 값을 증가해주기.
for (int i = 0; i < arr.length; i++) {
counting[arr[i]]++;
}
// 과정 3 - counting 배열을 누적합으로 만들어주기.
for (int i = 1; i < counting.length; i++) {
counting[i] += counting[i - 1];
}
// 과정 4 - 뒤에서부터 배열을 돌면서, 해당하는 값의 인덱스에 값을 넣어주기.
for (int i = arr.length - 1; i >= 0; i--) {
sorted_arr[counting[arr[i]] - 1] = arr[i];
counting[arr[i]]--;
}
기수 정렬(Radix Sort)

- 정의: 정수를 자릿수 별로 비교하여 정렬하는 알고리즘
- 목적: 자릿수 기반의 정수 데이터를 다룰 때 효율적이며, 범위가 작고 자릿수가 일정한 정수 데이터에 적합
- 특징:
- 비교 기반 아님: 원소 간의 직접적인 비교 없이 자릿수에 따라 정렬
- 제자리 정렬 아님 - 보조 배열을 사용하여 각 자릿수별 정렬을 하기 때문에 추가 공간이 필요
- 안정 정렬(Stable Sort): 동일한 값의 순서가 유지됨
자바 코드
void radixSort(int[] arr) {
int max = getMax(arr); // 배열에서 최대값 찾기
for (int place = 1; max / place > 0; place *= 10) {
countingSort(arr, place);
}
}
외부 정렬
- 내부정렬: 입력이 주기억 장치(내부 메모리)에 있는 상태에서 정렬이 수행되는 정렬
- 외부정렬: 입력 크기가 매우 커서 읽고 쓰는 시간이 오래 걸리는 보조 기억 장치에 입력을 저장할 수밖에 없는 상태에서 수행되는 정렬
- 과정
1. 주 기억 장치에 수용할 만큼 블록으로 분할한 후, Read & 내부 정렬 진행

2. 정렬된 블록의 합병
- 정렬된 블록들을 반복적인 합병을 통해, 하나의 정렬된 거대한 블록으로 만듬
- 블록들을 부분적으로 주 기억 장치에 읽어, 합병을 수행

