계수 정렬(Count Sort)이란?
- 특정한 조건이 부합할때만 사용할 수 있지만 매우 빠르게 동작하는 정렬 알고리즘
- 계수 정렬은 데이터의 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때 + 가장 큰 데이터와 가장 작은 데이터가 백만정도 이하의 차이일때 효율적인 정렬 알고리즘이다.
- 모든 범위를 담을 수 있는 크기의 리스트를 선언하여 구현한다.
- 데이터의 개수가 N, 데이터 중 최대값이 K일 때 최악의 경우에도 수행 시간 O(N + K)를 보장한다.
예시를 통해 계수 정렬 이해하기
아래의 표와 같은 성적을 가지고 있는 학생들이 있다고 가정하고, 오름차순으로 아래 성적을 정렬한다고 생각해보자. 누가 어떤 성적을 가지고 있는지는 중요하지 않다고 할 때, 계수 정렬을 이용하여 정렬하는 것이 가장 빠른 정렬 방법이다.
| 75 | 90 | 75 | 80 | 90 | 95 | 100 | 100 | 95 | 90 |
| 75 | 70 | 85 | 80 | 75 | 80 | 90 | 95 | 100 | 50 |
Step 0 : 성적은 "0" 점 부터 "100" 점 까지 정수로 나타내어 질 것이다. 따라서, "0" 부터 "100" 까지의 크기를 갖는 리스트를 선언해주면 된다. 아래와 같이 리스트를 선언해주고 해당 성적이 나온 개수를 리스트에 저장하면 된다. 실제로 리스트는 "0" 부터 "100" 까지 전부 선언되지만, 아래 표는 간략하게 나타낸 것이다.
| 50 | ... | ... | 70 | 75 | 80 | 85 | 90 | 95 | 100 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Step 1 : 앞의 데이터부터 하나씩 확인하며 해당하는 데이터가 나올때마다 리스트에 +1 씩 해주면 된다. "75" 를 확인하고 +1 을 해주면 리스트에 아래와 같이 저장될 것이다.
| 50 | ... | ... | 70 | 75 | 80 | 85 | 90 | 95 | 100 |
| 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
Step 2 : 그 다음 데이터인 "90" 을 확인하고 +1 을 해주면 된다. 이후, 이를 계속해서 반복한다.
| 50 | ... | ... | 70 | 75 | 80 | 85 | 90 | 95 | 100 |
| 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
중략
그럼 아래와 같이 리스트가 정리될 것이다.
| 50 | ... | ... | 70 | 75 | 80 | 85 | 90 | 95 | 100 |
| 1 | 0 | 0 | 1 | 4 | 3 | 1 | 4 | 3 | 3 |
리스트가 정리되었다면, 리스트의 앞에서부터 확인하며 해당 데이터의 개수 만큼 출력해주면 정렬은 완료된다. 맨 앞에 "50" 이라는 데이터가 "1" 개 있으니, "50" 은 "1" 번 출력해주면 된다. 이를 반복하여, "70" 은 "1" 번, "75" 는 "4" 번 출력해주면 될 것이다. 이를 반복하면 아래와 같이 정리된다.
| 50 | 70 | 75 | 75 | 75 | 75 | 80 | 80 | 80 | 85 |
| 90 | 90 | 90 | 90 | 95 | 95 | 95 | 100 | 100 | 100 |
Python을 이용하여 계수 정렬 구현
# 성적 데이터 입력
arr = [75, 90, 75, 80, 90, 95, 100, 100, 95, 90, 75, 70, 85, 80, 75, 80, 90, 95, 100, 50]
# 데이터의 모든 범위를 포함하는 리스트 선언, 모든 값은 0으로 초기화
count = [0] * (max(arr) + 1)
for i in range(len(arr)):
count[arr[i]] += 1 # 각 데이터에 해당하는 인덱스의 값 하나씩 증가
for i in range(len(count)): # 리스트에 기록된 정렬 정보 하나씩 확인
for j in range(count[i]):
print(i, end=' ') # 기록된 정보 출력
계수 정렬의 시간, 공간 복잡도
데이터의 개수를 N, 데이터 중 최대값의 크기를 K라고 할때, 계수 정렬의 시간 복잡도와 공간 복잡도는 둘 다 아래와 같다. $$ O(N + K) $$
앞에서부터 하나씩 데이터를 확인해야하고, 리스트에 저장된 값들을 데이터 중 최댓값의 크기만큼 반복하며 출력해야하기 때문이다.
계수 정렬의 특징
- 데이터의 범위만 한정되어 있고, 데이터의 크기가 많이 중복되어 있으면 있을수록 빠르게 동작하는 정렬 알고리즘이다.
- 데이터의 최댓값과 최솟값의 차이가 크면 클수록 선언해야하는 리스트의 크기가 커지므로 특정 상황에는 비효율적인 정렬 알고리즘이다.
- 실수형 데이터는 구현하기 힘들며, 정수형 데이터일수록 효율적으로 사용할 수 있다.
'Algorithm' 카테고리의 다른 글
| [알고리즘] 🤪 이죵과 병합정렬(Merge Sort)에 대해서 알아보자 (0) | 2024.08.25 |
|---|---|
| [BOJ 14442 벽 부수고 이동하기 2]로 알아보는 조건이 있는 BFS (0) | 2024.08.04 |
| [알고리즘] 🤪이죵과 다익스트라(Dijkstra) 알고리즘을 알아보자 (3) | 2024.07.22 |
| [알고리즘] 이분 탐색 (2) | 2024.07.21 |
| [BOJ 18222 투에-모스 문자열]을 이진법을 이용해 풀어보자 (0) | 2024.07.21 |