3-Way Merge Sort (삼분 병합 정렬)
3-Way Merge Sort은 병합 정렬(Merge Sort)의 변형으로, 배열을 세 개의 하위 배열로 분할하여 각각을 재귀적으로 정렬한 후 병합하는 정렬 알고리즘입니다.
이는 기본 병합 정렬에서 두 개의 하위 배열로 나누는 대신, 세 개로 나누어 처리 속도를 개선하려는 시도입니다.
1. 작동 원리
- 분할 (Divide):
- 주어진 배열을 세 개의 하위 배열로 나눕니다.
- 각각의 크기는 최대한 균등하게 나뉩니다.
- 정복 (Conquer):
- 세 개의 하위 배열을 재귀적으로 3-Way Merge Sort를 적용해 정렬합니다.
- 병합 (Merge):
- 세 개의 정렬된 배열을 병합하여 하나의 정렬된 배열로 만듭니다.
2. 알고리즘 특징
- 시간 복잡도:
- 평균 및 최악의 경우 O(n log3 n).
- 이는 병합 정렬(O(n log2 n)보다 약간 더 나은 성능을 제공할 수 있습니다.
- 공간 복잡도:
- O(n)의 추가 공간이 필요합니다(병합 단계에서).
- 안정성:
- 병합 정렬과 마찬가지로 안정 정렬입니다.
- 재귀 깊이 감소:
- 병합 정렬에 비해 재귀 깊이가 줄어듭니다.
3. 3-Way Merge Sort 과정
예시: 배열 [9, 7, 5, 3, 1, 8, 6, 4, 2]
- 분할:
- 배열을 세 부분으로 나눕니다:
- Left: [9, 7, 5]
- Middle: [3, 1, 8]
- Right: [6, 4, 2]
- 배열을 세 부분으로 나눕니다:
- 재귀적으로 정렬:
- Left → [5, 7, 9]
- Middle → [1, 3, 8]
- Right → [2, 4, 6]
- 병합:
- 세 정렬된 배열을 병합하여 최종 결과를 얻습니다:
- [1, 2, 3, 4, 5, 6, 7, 8, 9]
- 세 정렬된 배열을 병합하여 최종 결과를 얻습니다:
4. 장점과 단점
장점:
- 효율성: 하위 배열의 개수를 늘려 재귀 깊이를 줄임으로써 실행 속도를 향상시킬 수 있습니다.
- 안정성: 동일한 값을 가진 데이터의 상대적 순서를 유지합니다.
단점:
- 추가 메모리 사용: 병합 단계에서 추가 공간이 필요합니다.
- 병합 복잡성 증가: 두 개의 배열을 병합하는 것보다 세 개를 병합하는 것이 더 복잡합니다.
5. Java 구현
import java.util.Arrays;
public class ThreeWayMergeSort {
// Main function to perform 3-way merge sort
public static void threeWayMergeSort(int[] arr) {
if (arr.length <= 1) {
return;
}
// Step 1: Divide the array into three parts
int third = arr.length / 3;
int[] left = Arrays.copyOfRange(arr, 0, third);
int[] middle = Arrays.copyOfRange(arr, third, 2 * third);
int[] right = Arrays.copyOfRange(arr, 2 * third, arr.length);
// Step 2: Recursively sort each part
threeWayMergeSort(left);
threeWayMergeSort(middle);
threeWayMergeSort(right);
// Step 3: Merge the three sorted parts
merge(arr, left, middle, right);
}
// Helper function to merge three sorted arrays
private static void merge(int[] arr, int[] left, int[] middle, int[] right) {
int i = 0, j = 0, k = 0, l = 0;
while (i < left.length && j < middle.length && k < right.length) {
if (left[i] <= middle[j] && left[i] <= right[k]) {
arr[l++] = left[i++];
} else if (middle[j] <= left[i] && middle[j] <= right[k]) {
arr[l++] = middle[j++];
} else {
arr[l++] = right[k++];
}
}
while (i < left.length && j < middle.length) {
arr[l++] = (left[i] <= middle[j]) ? left[i++] : middle[j++];
}
while (j < middle.length && k < right.length) {
arr[l++] = (middle[j] <= right[k]) ? middle[j++] : right[k++];
}
while (i < left.length && k < right.length) {
arr[l++] = (left[i] <= right[k]) ? left[i++] : right[k++];
}
while (i < left.length) {
arr[l++] = left[i++];
}
while (j < middle.length) {
arr[l++] = middle[j++];
}
while (k < right.length) {
arr[l++] = right[k++];
}
}
// Main driver
public static void main(String[] args) {
int[] arr = {9, 7, 5, 3, 1, 8, 6, 4, 2};
System.out.println("Original Array: " + Arrays.toString(arr));
threeWayMergeSort(arr);
System.out.println("Sorted Array: " + Arrays.toString(arr));
}
}
6. Python 구현
def three_way_merge_sort(arr):
if len(arr) <= 1:
return arr
# Step 1: Divide the array into three parts
third = len(arr) // 3
left = arr[:third]
middle = arr[third:2*third]
right = arr[2*third:]
# Step 2: Recursively sort each part
left = three_way_merge_sort(left)
middle = three_way_merge_sort(middle)
right = three_way_merge_sort(right)
# Step 3: Merge the three sorted parts
return merge(left, middle, right)
# Helper function to merge three sorted arrays
def merge(left, middle, right):
result = []
i = j = k = 0
while i < len(left) and j < len(middle) and k < len(right):
if left[i] <= middle[j] and left[i] <= right[k]:
result.append(left[i])
i += 1
elif middle[j] <= left[i] and middle[j] <= right[k]:
result.append(middle[j])
j += 1
else:
result.append(right[k])
k += 1
while i < len(left) and j < len(middle):
result.append(left[i] if left[i] <= middle[j] else middle[j])
i += (left[i] <= middle[j])
j += (left[i] > middle[j])
while j < len(middle) and k < len(right):
result.append(middle[j] if middle[j] <= right[k] else right[k])
j += (middle[j] <= right[k])
k += (middle[j] > right[k])
while i < len(left) and k < len(right):
result.append(left[i] if left[i] <= right[k] else right[k])
i += (left[i] <= right[k])
k += (left[i] > right[k])
result.extend(left[i:])
result.extend(middle[j:])
result.extend(right[k:])
return result
# Example usage
if __name__ == "__main__":
arr = [9, 7, 5, 3, 1, 8, 6, 4, 2]
print("Original Array:", arr)
sorted_arr = three_way_merge_sort(arr)
print("Sorted Array:", sorted_arr)
7. 활용 및 고려사항
활용:
- 재귀 깊이 제한: 재귀 호출 스택 크기를 줄이기 위해 사용됩니다.
- 특수 목적 정렬: 병합 정렬의 효율성을 높이고자 할 때 사용.
고려사항:
- O(n log3 n)의 시간 복잡도는 병합 정렬보다 약간 개선되지만, 대부분의 실용적인 경우 이점이 미미할 수 있습니다.
- 병합 로직이 병합 정렬보다 복잡합니다.
3-Way Merge Sort는 이론적 흥미를 위한 알고리즘으로, 실무에서는 일반 병합 정렬보다 자주 사용되지 않습니다.
반응형
'컴퓨터과학 > 알고리즘' 카테고리의 다른 글
정렬 알고리즘 (Sorting Algorithms) - 기수 정렬 (Radix Sort) (0) | 2025.01.07 |
---|---|
정렬 알고리즘 (Sorting Algorithms) - 카운팅 정렬 (Counting Sort) (0) | 2025.01.07 |
정렬 알고리즘 (Sorting Algorithms) - 사이클 정렬 (Cycle Sort) (0) | 2025.01.07 |
정렬 알고리즘 (Sorting Algorithms) - 힙 정렬 (Heap Sort) (0) | 2024.12.28 |
정렬 알고리즘 (Sorting Algorithms) - 삽입 정렬 (Insertion Sort) (1) | 2024.12.27 |