병합 정렬(Merge Sort)은 “분할 정복(Divide and Conquer)” 알고리즘의 대표적인 예로, 리스트를 점점 더 작은 부분으로 나누어 각각을 정렬한 후, 다시 합쳐서 전체를 정렬하는 방식입니다. 병합 정렬의 기본 아이디어는 다음과 같습니다
- 분할(Divide): 리스트를 절반으로 나누어 두 개의 하위 리스트로 만든다.
- 정복(Conquer): 각 하위 리스트를 재귀적으로 병합 정렬을 이용해 정렬한다.
- 결합(Combine): 두 개의 정렬된 하위 리스트를 하나의 정렬된 리스트로 합친다.
이 과정을 반복하여 리스트를 완전히 정렬된 상태로 만듭니다. 병합 정렬의 시간 복잡도는 O(n log n)으로, 비교적 큰 데이터 세트에서도 효율적입니다.
public class MergeSort {
// 병합 정렬 함수
public static void mergeSort(int[] array, int left, int right) {
if (left < right) {
// 중간 지점을 계산
int mid = (left + right) / 2;
// 중간 지점을 기준으로 리스트를 두 개의 하위 리스트로 나누고 재귀적으로 정렬
mergeSort(array, left, mid);
mergeSort(array, mid + 1, right);
// 정렬된 두 하위 리스트를 병합
merge(array, left, mid, right);
}
}
// 병합 함수
public static void merge(int[] array, int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
// 두 개의 하위 리스트를 임시 배열에 저장
int[] leftArray = new int[n1];
int[] rightArray = new int[n2];
for (int i = 0; i < n1; ++i)
leftArray[i] = array[left + i];
for (int j = 0; j < n2; ++j)
rightArray[j] = array[mid + 1 + j];
// 병합 과정
int i = 0, j = 0;
int k = left;
while (i < n1 && j < n2) {
if (leftArray[i] <= rightArray[j]) {
array[k] = leftArray[i];
i++;
} else {
array[k] = rightArray[j];
j++;
}
k++;
}
// 남은 요소들 처리
while (i < n1) {
array[k] = leftArray[i];
i++;
k++;
}
while (j < n2) {
array[k] = rightArray[j];
j++;
k++;
}
}
// 테스트 함수
public static void main(String[] args) {
int[] array = {12, 11, 13, 5, 6, 7};
System.out.println("정렬 전 배열:");
for (int num : array) {
System.out.print(num + " ");
}
mergeSort(array, 0, array.length - 1);
System.out.println("\n정렬 후 배열:");
for (int num : array) {
System.out.print(num + " ");
}
}
}