본문 바로가기
알고리즘

병합 정렬

by 휘성티비 2024. 2. 18.

 

다음 수를 오름차순 정렬하시오

>7 6 5 8 3 5 9 1

 

병합 정렬

시간복잡도

병합 정렬도 분할 정복 알고리즘이기에 퀵 정렬과 같이 시간복잡도가 O(N*logN)이다.

 

정렬 구조

일단 나누고 나중에 합쳐서 정렬하는 방식이다. 퀵 정렬과 다르게 피벗 값이 없고 항상 반으로 나눈다는 특징을 가지고 있다. 이 특징이 단계의 크기를 logN이 되도록 만들어준다.

 

(S) | 7 | 6 | 5 | 8 | 3 | 5 | 9 | 1 |

(1) | 6 7 | 5 8 | 3 5 | 1 9|

(2) | 5 6 7 8 | 1 3 5 9|

(3) | 1 3 5 5 6 7 8 9 |

 

이런 방식이 N*logN을 만드는 원리가 무엇일까

 

먼저 너비는 숫자의 개수인 N(=8)이라고 할 수 있다. 하지마 세로는 3개이다 이때 log2N은 3이다.

 

따라서 반반씩 쪼개서 처리하면 데이터의 개수가 지수적으로 증가한다. 그러기에 작은 단계만 확인해도 전체 데이터를 확인할 수 있고 따라서 병합 정렬은 N*logN을 보장한다고 할 수 있다.

 

너비가 왜 N인지 궁금할 수 있다. 각 단계마다 비교해야 할 데이터 수가 N이라고 할 수 있다.

 

#include<bits/stdc++.h>
using namespace std;
int number = 8;
int sorted[8]; //정렬 배열은 반드시 전역 변수 

void merge(int a[], int m, int middle, int n){
	int i = m;
	int j = middle + 1;
	int k = m;
	// 작은 순서대로 배열에 삽입 
	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) {
	if(m<n){
		int middle = (m+n)/2;
		mergeSort(a,m,middle);
		mergeSort(a,middle+1, n);
		merge(a,m,middle,n);
	}
}
int main()
{
	int arr[number] = {7,6,5,8,3,5,9,1};
	mergeSort(arr, 0 ,number-1);
	for(int i=0; i<number; i++)
		cout << arr[i] << ' ';
	return 0;
}

'알고리즘' 카테고리의 다른 글

버블 정렬  (0) 2024.02.18
삽입 정  (0) 2024.02.18
퀵 정렬  (0) 2024.02.18
힙 정렬  (0) 2024.02.18
계수 정렬  (0) 2024.02.18