-
정렬 알고리즘 (9): 버킷 정렬 (Bucket Sort)알고리즘 2025. 2. 20. 16:00
1. 버킷 정렬이란?
버킷 정렬(Bucket Sort)은 데이터를 여러 개의 버킷(bucket)으로 나누어 정렬하는 비교 기반이 아닌 정렬 알고리즘이다. 각 버킷은 일정한 범위를 가지며, 데이터가 해당 범위에 따라 버킷에 배정된 후 개별적으로 정렬되고, 이후 병합되어 최종적으로 정렬된 배열을 얻는다.
이 알고리즘은 입력 데이터가 고르게 분포된 경우 매우 효율적으로 동작하며, 평균적으로 O(n + k)의 시간 복잡도를 가진다. 일반적으로 삽입 정렬, 병합 정렬 또는 퀵 정렬을 보조적으로 사용하여 개별 버킷을 정렬한다.
2. 버킷 정렬의 동작 원리
버킷 정렬은 다음과 같은 과정을 거쳐 데이터를 정렬한다.
2.1 정렬 과정
- 입력 배열의 최댓값과 최솟값을 찾는다.
- 범위를 기반으로 여러 개의 버킷을 생성한다.
- 각 요소를 해당하는 버킷에 배치한다.
- 각 버킷을 개별적으로 정렬한다.
- 모든 버킷을 병합하여 최종적으로 정렬된 배열을 만든다.
2.2 예제 코드 (Java)
import java.util.*; public class BucketSort { // 버킷 정렬을 수행하는 메서드 public static void bucketSort(float[] arr, int bucketSize) { if (arr.length == 0) return; // 최댓값과 최솟값 찾기 float minValue = arr[0]; float maxValue = arr[0]; for (float num : arr) { if (num < minValue) minValue = num; if (num > maxValue) maxValue = num; } // 버킷 개수 결정 int bucketCount = (int) Math.ceil((maxValue - minValue) / bucketSize) + 1; List<List<Float>> buckets = new ArrayList<>(bucketCount); for (int i = 0; i < bucketCount; i++) { buckets.add(new ArrayList<>()); } // 각 숫자를 해당하는 버킷에 배치 for (float num : arr) { int bucketIndex = (int) ((num - minValue) / bucketSize); buckets.get(bucketIndex).add(num); } // 각 버킷을 개별적으로 정렬 for (List<Float> bucket : buckets) { Collections.sort(bucket); } // 정렬된 요소를 원본 배열에 병합 int index = 0; for (List<Float> bucket : buckets) { for (float num : bucket) { arr[index++] = num; } } } // 메인 메서드: 버킷 정렬 실행 및 결과 출력 public static void main(String[] args) { float[] data = {0.42f, 0.32f, 0.33f, 0.52f, 0.37f, 0.47f, 0.51f}; System.out.println("정렬 전: " + Arrays.toString(data)); bucketSort(data, 10); System.out.println("정렬 후: " + Arrays.toString(data)); } }
3. 버킷 정렬의 성능 분석
버킷 정렬의 시간 및 공간 복잡도를 분석하면 다음과 같다.
3.1 시간 복잡도
- 최선의 경우 (Best Case): O(n) → 데이터가 고르게 분포된 경우
- 평균의 경우 (Average Case): O(n + k) → k는 버킷 개수
- 최악의 경우 (Worst Case): O(n²) → 모든 요소가 하나의 버킷에 배치될 경우
3.2 공간 복잡도
- 공간 복잡도: O(n + k) → 추가적인 버킷 배열이 필요하므로 메모리 사용량이 증가할 수 있음.
4. 버킷 정렬의 장점과 단점
4.1 장점
- 비교 기반 정렬 알고리즘보다 빠를 수 있음 (특히 데이터가 균등하게 분포된 경우).
- O(n) 또는 O(n + k)로 동작할 가능성이 높아 매우 빠른 성능을 보일 수 있음.
- 안정 정렬(Stable Sort)이며, 동일한 값의 상대적 순서를 유지할 수 있음.
4.2 단점
- 추가적인 메모리 공간이 필요하여 공간 복잡도가 증가할 수 있음.
- 데이터가 균등하게 분포되지 않은 경우 최악의 경우 O(n²)의 성능을 가질 수 있음.
- 버킷의 크기와 개수를 적절하게 설정해야 최적의 성능을 낼 수 있음.
5. 버킷 정렬의 활용 및 개선 방법
5.1 활용 사례
- 부동소수점 데이터를 정렬할 때 유용함.
- 데이터가 균등하게 분포된 경우 빠르게 정렬할 수 있음.
- 대량의 데이터를 정렬해야 하는 경우 효율적으로 사용할 수 있음.
5.2 개선 방법
- 적절한 버킷 크기 선택: 버킷 크기가 너무 작거나 크면 성능이 저하될 수 있음.
- 보조 정렬 알고리즘 사용: 각 버킷을 정렬할 때 삽입 정렬이나 퀵 정렬을 혼합하여 최적화 가능.
- 동적 버킷 크기 조정: 데이터 분포를 분석하여 버킷 크기를 조정하면 성능을 개선할 수 있음.
6. 결론
버킷 정렬은 정수뿐만 아니라 실수 데이터를 정렬할 때 매우 효율적인 알고리즘이다. 비교 기반 정렬보다 빠를 수 있으며, 데이터가 균등하게 분포된 경우 O(n) 성능을 기대할 수 있다. 하지만 메모리 사용량이 증가할 수 있고, 데이터 분포에 따라 성능이 저하될 수도 있으므로 적절한 상황에서 사용하는 것이 중요하다.
'알고리즘' 카테고리의 다른 글
탐색 알고리즘 (1): 순차 탐색 (Linear Search) (0) 2025.02.25 탐색 알고리즘: 개념, 종류 및 성능 비교 (0) 2025.02.24 정렬 알고리즘 (8): 기수 정렬 (Radix Sort) (0) 2025.02.19 정렬 알고리즘 (7): 계수 정렬 (Counting Sort) (0) 2025.02.18 정렬 알고리즘 (6): 힙 정렬 (Heap Sort) (0) 2025.02.17