병합 정렬(Merge Sort)은 분할 정복(Divide and Conquer) 방법을 이용한 효율적인 정렬 알고리즘이다. 이 알고리즘은 배열을 반복적으로 반으로 나누고, 더 이상 나눌 수 없을 때까지 분할한 후, 다시 합병하면서 정렬하는 방식이다. 병합 정렬은 안정 정렬에 속하며, 시간 복잡도가 O(n log n)으로 매우 효율적이다.
병합 정렬 구현
public class MergeSort {
private static int[] sorted; // 임시 배열
public static void mergeSort(int[] a, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(a, left, mid); // 왼쪽 부분 배열 정렬
mergeSort(a, mid + 1, right); // 오른쪽 부분 배열 정렬
merge(a, left, mid, right); // 정렬된 부분 배열을 병합
}
}
private static void merge(int[] a, int left, int mid, int right) {
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) {
if (a[i] <= a[j]) {
sorted[k++] = a[i++];
} else {
sorted[k++] = a[j++];
}
}
// 왼쪽 부분 배열이 남아있다면 복사
while (i <= mid) {
sorted[k++] = a[i++];
}
// 오른쪽 부분 배열이 남아있다면 복사
while (j <= right) {
sorted[k++] = a[j++];
}
// 정렬된 배열을 원본 배열에 복사
for (int l = left; l <= right; l++) {
a[l] = sorted[l];
}
}
public static void main(String[] args) {
int[] arr = {6, 2, 4, 3, 7, 1, 9};
sorted = new int[arr.length]; // 임시 배열 초기화
mergeSort(arr, 0, arr.length - 1);
for (int i : arr) {
System.out.print(i + " ");
}
}
}
예제 배열: [6, 2, 4, 3, 7, 1, 9]
1. 분할 단계:
병합 정렬의 시간 복잡도는 분할과 병합 과정에서 각각 O(log n)과 O(n)의 시간이 소요되므로 전체적으로 O(n log n)이다.
병합 정렬은 임시 배열을 사용하여 정렬된 배열을 저장하기 때문에, 추가적인 메모리 공간이 필요하다. 따라서 공간 복잡도는 O(n)이다.
병합 정렬은 순차적인 접근이 효율적인 LinkedList 정렬에 매우 유용하다. 반면, 퀵 정렬은 임의 접근이 효율적이므로 배열 정렬에 더 적합하다. 따라서 병합 정렬은 LinkedList와 같은 자료 구조에서 유리한 성능을 보인다.
병합 정렬은 안정적이고 효율적인 정렬 알고리즘으로, 특히 데이터의 크기와 분포에 관계없이 일정한 성능을 보장한다. 다만, 추가적인 메모리 공간을 필요로 하므로 메모리 사용에 민감한 환경에서는 주의가 필요하다. 오늘 학습을 통해 병합 정렬의 동작 원리와 장단점을 이해하고, 이를 적절히 활용할 수 있는 상황을 파악할 수 있었다.