/ ALGORITHM

<정렬> 병합 정렬(Merge Sort)


[ 일단 반으로 나누고 나중에 합쳐서 정렬해보자 ]
퀵 정렬과 다르게 피벗 값이 없고 무조건 반으로 모두 나누고 합하면서 정렬한다는 방법이다.

ex_screenshot

실제로 각 다른 배열을 갖는것이아니라 논리적으로 그렇다고 생각하고 그림처럼 정렬시킨다.
각 하나로 만들고 분할 병합하며 정렬하는 방식이다.

더 자세히 코드느낌으로 보자면
ex_screenshot 나누어진 두 배열을 비교하며 작은 값을 k인덱스에 하나씩 집어넣는다.
이 때 실제로 k은 새로운 배열이 아니라 i와 같은 배열이다.

[병합 정렬의 시간 복잡도 O(N* log2N) ]

ex_screenshot 배열의 (너비) N * (높이) log2 N = O(N*log2 N) 시간복잡도가 나온다.

어째서 정렬에 높이 log2 N 밖에 안나오냐라는 질문에는 이미 정렬된 두 배열을 정렬하기 때문이라고 답할 수 있다.

실제로 나누어진 두 배열을 하나로 합하며 정렬해 나갈때 N번의 반복만 수행이 된다.
내가 이해한 루트로 설명해보자면

1번째 줄에서 2번째 줄로 분할병합 할 때, 먼저 {6,5} {5,8}
1회전-> i(0)과 j(0)비교
2회전-> i(0)과 j(1)비교
3회전-> i(1)과 j(0)비교
4회전-> i(1)과 j(1)비교
총 4회 -> 배열의 총 크기만큼만 수행된다.
그렇다면 그 옆 배열 {3,5}, {1,9}의 분할병합에서도 4회의 반복이 될것이고
즉, 그림에 한 줄 N번의 수행을 한다라는것을 알 수 있다.

시간 복잡도가 퀵 정렬과 같은데 다른 점이라 하면
퀵 정렬은 정렬 알고리즘 중 가장 빠른 속도를 자랑하지만 최악의 경우에는 O(N^2)가 될 수 있는 정렬이고,
병합 정렬은 최악의 상황에서도 평균 O(N*logN)을 보장할 수 있다는 것이 큰 장점으로 쓰인다.

[코드를 살펴보자]

#include <stdio.h>

int number =8; 
int sorted[8]; // 정렬 배열은 반드시 전역 변수로 선언
 
//정렬된 배열을 담을 뱅
// 논리적으로 둘로 나누어진 i, j 배열을 정렬하며 합치는 메서드 merge 
										//n은 j의 끝 인덱스 
void merge(int a[], int m, int middle, int n ) {
	
	int i=m; // 왼쪽배열 시작점 
	int j = middle+1; // 한칸 띄움 
	int k=m; //정렬된 배열 
	//k는 사실상 i와 동일한 위치를 가진다. 
	// 그림은 정렬 전 배열과 정렬 후의 배열을 따로 두었지만
	// 실제로는 하나의 배열을 사용중  
	
	//작은 순서대로 배열에 삽입 
	while (i <=middle && j <= n ) {
		if (a[i] <= a[j]) {
			sorted[k]= a[i];
			i++;
		}else {
			sorted[k]= a[j];
			j++;
		}
		k++;	
	}
	
	//남은 데이터도 삽입 
	if (i>middle) {
		for (int t=j; t<=n; t++) {
			sorted[k]= a[t];
			k++;
		}
		
	} else {
		for (int t=i; t<=middle; t++) {
			sorted[k] = a[t];
			k++;
			
		}
	}
	// 정렬된 배열을 삽입
	for(int t=m; t<=n; t++) {
		a[t] = sorted[t];
	} 
	
	
}
 
void mergeSort(int a[], int m, int n) {
	//크기가 1보다 큰 경우
	if(m <n) {
		int middle = (m+n) /2;
		mergeSort(a,m,middle);
		mergeSort(a, middle+1, n );
		merge(a, m, middle, n);
	}
}
int main(void) {
	int array[number] = {7,6,5,8,3,5,9,2} ;
	mergeSort(array, 0, number-1);
	for (int i=0; i<number; i++ ) {
		printf("%d ", array[i]);
	}
}

References
강의영상
https://www.youtube.com/watch?v=ctkuGoJPmAE&list=PLRx0vPvlEmdDHxCvAQS1_6XV4deOwfVrz&index=8
사진첨부
https://blog.naver.com/ndb796/221227934987