알고리즘/정렬
병합 정렬
Dero Lee
2021. 12. 25. 00:18
728x90
병합 정렬: 모든 원소들이 하나로 남을때까지 정확하게 절반으로 나눈 후 나중에 합쳐서 정렬하는 알고리즘.
Ex)
(이미 하나까지 전부 반으로 쪼게진 상태라 가정하고 2의 배수만큼 차례대로 합쳐진다.)
7 6 5 8 3 5 9 1
67 58 35 19
5678 1359
13556789
시간 복잡도: O(N*log N)
너비가 n이고 높이가 log n
(정렬이 되어있는 상태에서 데이터를 하나씩 읽어나가 새롭게 정렬을 하므로 n * log n에 비례.)
병합 정렬의 경우 항상 정확히 절반으로 분할되고 정복하는 과정이 반복되므로 최악의 경우에도 O(N*log N)을 보장한다. (퀵 정렬은 편향되게 분할 할 가능성이 있으므로 최악의 경우 O(N^2))
단점: 기존의 데이터를 담을 추가적인 배열 공간이 필요하여 메모리 활용이 비효율적임.
#include <stdio.h>
int n = 10;
int sorted_arr[10];
/* 병합 정렬에서는 추가적인 배열이 필요한데, 전역 변수로 배열을 선언하게 되면 모든 함수가
공통적으로 이용할 수 있기때문에 불필요한 메모리 사용을 최소화할 수 있다. */
void merge(int arr[], int start, int mid, int end);
void mergeSort(int arr[], int start, int end);
int main() {
int arr[n] = {7, 6, 5, 8, 4, 5, 9, 2, 10, 1};
mergeSort(arr, 0, n-1);
for(int i = 0; i<n; i++) {
printf("%d ",arr[i]);
}
}
void merge(int arr[], int start, int mid, int end) {
int i = start;
int j = mid+1;
int k = start;
// 작은 순서대로 배열에 삽입.
while(i<=mid && j<=end) {
if(arr[i] <= arr[j]) {
sorted_arr[k] = arr[i];
i++;
}
else {
sorted_arr[k] = arr[j];
j++;
}
k++;
}
// 남은 데이터도 삽입
if(i > mid) {
for(int t = j; t<=end; t++) {
sorted_arr[k] = arr[t];
k++;
}
}
else {
for(int t = i; t<=mid; t++) {
sorted_arr[k] = arr[t];
k++;
}
}
// 정렬된 배열을 실제 배열로 삽입
for(int t = start; t<=end; t++) {
arr[t] = sorted_arr[t];
}
}
// 크기가 1일때까지 반으로 나누고 최종적으로 합쳐서 정렬
void mergeSort(int arr[], int start, int end) {
// 크기가 1보다 큰 경우
if(start<end) {
int mid = (start + end)/2;
mergeSort(arr, start, mid);
mergeSort(arr, mid+1, end);
merge(arr, start, mid, end);
}
}
728x90