원소 개수가 1 또는 0이 될 때까지 두 부분으로 쪼개고 쪼개서 자른 순서의 역순으로 크기를 비교해 병합해 나가는 정렬 방식

흔히 쓰이는 하향식 2-way 합병 정렬은 다음과 같이 작동한다.

import java.util.Arrays;
public class MergeSort {
static int[] sortedArr;
public static void main(String[] args) {
int[] arr = { 77, 32, 37, 17, 22, 8, 13, 42, 26 };
sortedArr = new int[arr.length];
System.out.println("정렬전: " + Arrays.toString(arr));
mergeSort(arr, 0, arr.length-1);
System.out.println("정렬후: " + Arrays.toString(arr));
}
// arr : 내가 정렬하고자 하는 배열 / left ,right 경계,위치
public static void mergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid); // (1) 왼쪽 절반 분할
mergeSort(arr, mid + 1, right); // (1) 오른쪽 절반 분할
merge(arr, left, mid, right); // (2) 분할된 집합 병합
}
}
public static void merge(int[] arr, int left, int mid, int right) {
int L = left; // 왼쪽 구간 시작 인덱스
int R = mid + 1; // 오른쪽 구간 시작 인덱스
int idx = left; // 정렬된 원소 저장할 위치
while (L <= mid && R <= right) { // 어느 한 쪽이 끝까지 도달하지 않았을 때
// 분할된 부분들 중 더 작은 부분을 삽입
if (arr[L] <= arr[R])
sortedArr[idx++] = arr[L++]; // 값들을 넣고 증가시킨다.
else
sortedArr[idx++] = arr[R++];
}
// 왼쪽구간이 남았다면
if (L <= mid) { // (3)
for (int i = L; i <= mid; i++)
sortedArr[idx++] = arr[i];
}
// 오른쪽구간이 남았다면
else { // (3)
for (int i = R; i <= right; i++)
sortedArr[idx++] = arr[i];
}
// 정렬한 임시배열을 원 배열에 저장한다.
for (int i = left; i <= right; i++)
arr[i] = sortedArr[i];
System.out.println(Arrays.toString(arr));
}
}
정렬전: [77, 32, 37, 17, 22, 8, 13, 42, 26]
[32, 77, 37, 17, 22, 8, 13, 42, 26]
[32, 37, 77, 17, 22, 8, 13, 42, 26]
[32, 37, 77, 17, 22, 8, 13, 42, 26]
[17, 22, 32, 37, 77, 8, 13, 42, 26]
[17, 22, 32, 37, 77, 8, 13, 42, 26]
[17, 22, 32, 37, 77, 8, 13, 26, 42]
[17, 22, 32, 37, 77, 8, 13, 26, 42]
[8, 13, 17, 22, 26, 32, 37, 42, 77]
정렬후: [8, 13, 17, 22, 26, 32, 37, 42, 77]
(1)에서 mergeSort 메소드는 재귀를 이용해 right<=left가 될 때 까지(분할된 크기가 1 이하가 될 때까지) 분할을 진행한다. 분할이 모두 이루어졌으면 (1)의 메소드들은 실행할 내용이 없고, (2)의 merge 메소드를 실행하여 병합을 진행한다. sortedArr의 idx를 증가시켜가며, 오름차순의 경우 arr[L]과 arr[R]중 더 작은 것을 집어넣고 L 혹은 R을 증가시킨다.
(3)에서는 배열의 왼쪽과 오른쪽에 남은 것들을 마지막 순서에 집어넣는다.
아래에서는 편의를 위해 원소를 인덱스로 설명하자면,
mergeSort(0,8)mergeSort(0,8) mergeSort(0,4)mergeSort(0,8) mergeSort(0,4) mergeSort(0,2)mergeSort(0,8) mergeSort(0,4) mergeSort(0,2) mergeSort(0,1)mergeSort(0,1)에서 호출한 mergeSort(0,0)은 실행하지 않고 mergeSort(1,1)도 실행하지 않는다. merge(0,0,1)을 호출하여 arr의 0부터 1까지를 정렬한다.mergeSort(0,8) mergeSort(0,4) mergeSort(0,2)mergeSort(0,2)에서 mergeSort(0,1)을 끝냈으니 다음 줄에서 mergeSort(2,2)를 호출하지만, left==right이므로 실행하지 않는다. 다음 줄에서 merge(0,1,2)를 실행하여 0부터 2까지 정렬한다.mergeSort(0,8) mergeSort(0,4) mergeSort(0,4) 에서 실행한 mergeSort(0,2)가 완료되었으니 mergeSort(3,4)를 호출한다.mergeSort(0,8) mergeSort(0,4) mergeSort(3,4)mergeSort(3,4)에서 mergeSort(3,3)는 left==right이므로 실행하지 않고, mergeSort(4,4) 또한 실행하지 않는다. 다음 줄에서 바로 merge(3,3,4)를 실행한다.........
정렬전: [77, 32, 37, 17, 22, 8, 13, 42, 26]
mergeSort([77, 32, 37, 17, 22, 8, 13, 42, 26], 0, 8)
mergeSort([77, 32, 37, 17, 22, 8, 13, 42, 26], 0, 4)
mergeSort([77, 32, 37, 17, 22, 8, 13, 42, 26], 0, 2)
mergeSort([77, 32, 37, 17, 22, 8, 13, 42, 26], 0, 1)
mergeSort([77, 32, 37, 17, 22, 8, 13, 42, 26], 0, 0)
mergeSort([77, 32, 37, 17, 22, 8, 13, 42, 26], 1, 1)
merge([77, 32, 37, 17, 22, 8, 13, 42, 26], 0, 0, 1)
[32, 77, 37, 17, 22, 8, 13, 42, 26]
mergeSort([32, 77, 37, 17, 22, 8, 13, 42, 26], 2, 2)
merge([32, 77, 37, 17, 22, 8, 13, 42, 26], 0, 1, 2)
[32, 37, 77, 17, 22, 8, 13, 42, 26]
mergeSort([32, 37, 77, 17, 22, 8, 13, 42, 26], 3, 4)
mergeSort([32, 37, 77, 17, 22, 8, 13, 42, 26], 3, 3)
mergeSort([32, 37, 77, 17, 22, 8, 13, 42, 26], 4, 4)
merge([32, 37, 77, 17, 22, 8, 13, 42, 26], 3, 3, 4)
[32, 37, 77, 17, 22, 8, 13, 42, 26]
merge([32, 37, 77, 17, 22, 8, 13, 42, 26], 0, 2, 4)
[17, 22, 32, 37, 77, 8, 13, 42, 26]
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 5, 8)
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 5, 6)
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 5, 5)
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 6, 6)
merge([17, 22, 32, 37, 77, 8, 13, 42, 26], 5, 5, 6)
[17, 22, 32, 37, 77, 8, 13, 42, 26]
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 7, 8)
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 7, 7)
mergeSort([17, 22, 32, 37, 77, 8, 13, 42, 26], 8, 8)
merge([17, 22, 32, 37, 77, 8, 13, 42, 26], 7, 7, 8)
[17, 22, 32, 37, 77, 8, 13, 26, 42]
merge([17, 22, 32, 37, 77, 8, 13, 26, 42], 5, 6, 8)
[17, 22, 32, 37, 77, 8, 13, 26, 42]
merge([17, 22, 32, 37, 77, 8, 13, 26, 42], 0, 4, 8)
[8, 13, 17, 22, 26, 32, 37, 42, 77]
정렬후: [8, 13, 17, 22, 26, 32, 37, 42, 77]
https://namu.wiki/w/%EC%A0%95%EB%A0%AC%20%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98#s-2.2.1
https://ko.wikipedia.org/wiki/%ED%95%A9%EB%B3%91_%EC%A0%95%EB%A0%AC
https://kangworld.tistory.com/74 (시간복잡도)