Menu
Coddy logo textTech

기수 정렬

마지막 업데이트

기수 정렬은 정수를 위한 비교하지 않는 정렬입니다. 값을 비교하는 대신 숫자를 자릿수별로 정렬합니다. 최하위 자릿수(LSD) 버전은 먼저 일의 자리를, 다음으로 십의 자리, 그다음 백의 자리를 처리하며 각 자릿수에서 안정적인 계수 정렬을 사용합니다. 각 패스가 안정적이므로 최상위 자릿수를 처리하고 나면 배열 전체가 정렬됩니다. 위의 재생 버튼을 눌러 각 자릿수 패스가 막대를 어떻게 재배열하는지 확인하세요.

기수 정렬은 O(d·(n + k)) 시간에 동작하며, 여기서 d는 자릿수, k는 기수(여기서는 10)입니다. 고정 폭 정수의 경우 사실상 선형이며 O(n log n) 비교 정렬을 능가할 수 있지만, 자릿수나 키로 분해할 수 있는 데이터에서만 작동합니다.

시간 및 공간 복잡도

경우복잡도비고
시간O(d·(n + k))d 자릿수, 기수 k (d가 고정이면 선형)
공간O(n + k)출력 배열 + 자릿수 카운트
안정성각 자릿수 패스는 안정적인 계수 정렬
비교 기반?아니오값을 비교하지 않고 자릿수로 정렬
적용 대상정수/키일반 비교 가능 객체에는 부적합

단계별 과정

단계무슨 일이 일어나는가
1처리할 자릿수를 알기 위해 최댓값을 찾는다.
2최하위 자릿수(일의 자리)부터 시작한다.
3계수 정렬을 사용해 해당 자릿수 기준으로 배열을 안정적으로 정렬한다.
4다음으로 더 높은 자릿수로 이동한다.
5모든 자릿수 위치를 처리할 때까지 반복한다.

예제 풀이

[170, 45, 75, 90, 2, 24, 66] 정렬:

패스배열동작
시작[170, 45, 75, 90, 2, 24, 66]최댓값이 170이므로 자릿수 패스가 세 번 필요하다.
일의 자리[170, 90, 2, 24, 45, 75, 66]일의 자리 기준 안정 정렬: 0, 0, 2, 4, 5, 5, 6.
십의 자리[2, 24, 45, 66, 170, 75, 90]십의 자리 기준 안정 정렬: 0, 2, 4, 6, 7, 7, 9 (17075보다 앞선 순서를 유지).
백의 자리[2, 24, 45, 66, 75, 90, 170]백의 자리 기준 안정 정렬. 1701을 가지므로 맨 뒤로 이동. 정렬 완료.

기수 정렬을 사용해야 할 때

사용하면 좋은 경우피해야 하는 경우
키가 자릿수로 나눌 수 있는 정수나 고정 길이 문자열일 때.사용자 정의 비교자로 임의의 객체를 정렬해야 할 때.
키의 자릿수 d가 작고 유한하여 O(d·(n + k))O(n log n)을 능가할 때.키가 매우 길거나 무한하여 d가 커지고 각 패스가 비싸질 때.
안정적인 정렬이 필요하고 O(n + k)의 추가 공간을 감당할 수 있을 때.메모리가 부족하여 O(n + k) 버퍼를 감당할 수 없을 때.
값의 범위나 기수 kn에 비해 적당할 때.k가 매우 커서 각 계수 정렬 패스가 실행 시간을 지배할 때.

Radix Sort 코드

Python, JavaScript, Java, C++, C로 작성된 깔끔하고 실행 가능한 Radix Sort 구현입니다. 언어를 선택해 코드를 복사하거나 Coddy 플레이그라운드에서 바로 열어보세요.

Python로 구현한 Radix Sort 코드

Python
1def radix_sort(a):2    # Sort by each decimal digit, least significant first3    max_value = max(a)4    exp = 15    while max_value // exp > 0:6        a = sort_by_digit(a, exp)7        exp *= 108    return a9
10
11def sort_by_digit(a, exp):12    buckets = [[] for _ in range(10)]13    for value in a:14        digit = (value // exp) % 1015        buckets[digit].append(value)16    # Concatenating buckets 0..9 keeps the sort stable17    return [value for bucket in buckets for value in bucket]18
19
20nums = [170, 45, 75, 90, 802, 24, 2, 66]21print("Before:", nums)22print("After: ", radix_sort(nums))
이 코드를 Python 플레이그라운드에서 실행하기

기수 정렬 자주 묻는 질문

기수 정렬의 시간 복잡도는 무엇인가요?
기수 정렬은 O(d·(n + k))이며, 여기서 d는 자릿수, k는 기수입니다. 고정 폭 정수의 경우 사실상 O(n)이 되어 비교 정렬보다 빠를 수 있습니다. O(n + k)의 추가 공간을 사용합니다.
기수 정렬은 안정적인가요?
예. LSD 기수 정렬은 각 자릿수에서 안정적인 계수 정렬에 의존하며, 이 안정성 덕분에 자릿수별 접근 방식이 올바르게 정렬된 결과를 만들어냅니다.
기수 정렬은 언제 사용할 수 있나요?
기수 정렬은 정수나 고정 길이 문자열처럼 자릿수나 고정 크기 키로 분해할 수 있는 데이터에서 작동합니다. 범용 비교 정렬이 아니므로 사용자 정의 비교자로 임의의 객체를 정렬할 수는 없습니다.
기수 정렬은 계수 정렬과 어떻게 다른가요?
계수 정렬은 하나의 키로 한 번의 패스에서 정렬하며 값 범위만큼 큰 카운트 배열이 필요하므로 값이 넓게 퍼져 있으면 성능이 저하됩니다. 기수 정렬은 계수 정렬을 자릿수별로 적용하여 각 패스의 카운트 배열을 작게(기수 k) 유지하므로, 단순 계수 정렬로는 처리할 수 없는 큰 값 범위를 다룰 수 있습니다.
왜 LSD 기수 정렬은 최하위 자릿수부터 시작하나요?
최하위 자릿수부터 시작하면 각 안정 패스가 이전의 더 낮은 자릿수들이 확립한 순서를 보존할 수 있습니다. 최상위 자릿수를 처리할 때쯤이면 그 자릿수가 같은 요소들은 이미 하위 자릿수에 의해 올바르게 정렬되어 있어, 배열이 최종적으로 완전히 정렬됩니다. 최상위 자릿수부터 먼저 정렬하면 이것이 깨지고 다른 재귀적 접근(MSD 기수 정렬)이 필요해집니다.
기수 정렬은 음수를 처리할 수 있나요?
직접적으로는 불가능합니다. 기본적인 자릿수 추출은 음이 아닌 정수를 가정합니다. 흔한 해결책은 최솟값을 더해 모든 값을 음이 아니게 오프셋하거나, 음수와 음이 아닌 수를 따로 정렬한 뒤 이어 붙이는 것입니다. 이를 무시하는 것은 기수 정렬을 실제 데이터에 적용할 때 자주 발생하는 버그입니다.
Coddy programming languages illustration

Coddy로 알고리즘을 마스터하세요

시작하기