..
Merge Sort
Concept
배열을 둘로 나눈다. 나눈 배열을 또 둘로 나눈다. 배열방이 2개씩 남았을때 Merge Sort를 할 수 있다.
Partition이 방 한개씩 딱 두개의 배열로 나눌 수 있을때 데이터를 가지고 병합을 한다.
끝의 제일 작은 부분부터 이렇게 병합해가면서 정렬된 배열을 Merge해 나가는 방법.
적용
함수가 호출될 때마다 절반씩 잘라서 재귀적으로 함수를 호출하고 맨 끝의 제일 작은 조각부터 두개씩 병합해서 정렬된 배열을 Merge해 나간다



Time complexity (시간 복잡도)

- Binary search에서 검색 영역이 절반씩 떨어지는 것과 같은 원리
- 물리적으로 가운데값으로 partition을 나눈다
- 최악의 경우 - O(n Log n)
- Quicksort로 따지면 pivot을 잘 골랐을 때와 같다
- 공간을 사용 할 수 없는 경우에는
quicksort를 이용해야 한다
Merge Sort 구현
public class Test {
private static void mergeSort(int[] arr) {
// 임시 저장 공간이 필요하다
int[] tmp = new int[arr.length];
mergeSort(arr, tmp, 0, arr.length-1); // 재귀 호출 시작
}
private static void mergeSort(int[] arr, int[] tmp, int start, int end){
if(start < end){
// 함수가 호출되면 배열을 가운데로 자른다
int mid = (start + end) / 2;
mergeSort(arr, tmp, start, mid);
mergeSort(arr, tmp, mid +1, end);
// 재귀함수가 돌아온 다음에는 합쳐줘야한다
// 이때는 가운데를 기준으로 왼쪽과 오른쪽이 정렬이 되어있는 상태
// 두개로 나뉘어 있는 배열 방을 Merge
merge(arr, tmp, start, mid, end);
}
}
private static void merge(int[] arr, int[] tmp, int start, int mid, int end){
// 임시 저장소에 필요한 만큼 배열을 복사해준다
for (int i = start; i <= end; i++){
tmp[i] = arr[i];
}
int part1 = start; // 첫 번째 배열 방의 첫번째 인덱스
int part2 = mid + 1; // 두 번째 배열 방의 첫번째 인덱스
int index = start;
while(part1 <= mid && part2 <= end){. // 첫 번째 배열의 끝이나 두 번째 배열의 끝에 다다르면
if(tmp[part1] <= tmp[part2]) {
arr[index] = tmp[part1];
part1++;
} else {
arr[index] = tmp[part2];
part2++;
}
index++;
}
// 앞쪽 배열에 데이터가 남아있는 경우, 뒤쪽 배열은 비어있다
for (int i=0; i <= mid - part1; i++){
arr[index + i] = tmp[part1 + i];
}
// 앞쪽 배열은 비어있고, 뒤쪽 배열에 데이터가 남아있는 경우
}
private static void printArray(int[] arr){
for(int data : arr){
System.out.println(data + ", ");
}
System.out.println();
}
public static void main(String[] args){
int[] arr = {3,9,4,7,5,0,1,6,8,2};
printArray(arr);
mergeSort(arr);
printArray(arr);
}
}