하나의 리스트를 두 개의 균등한 크기로 분할하고 분할된 부분 리스트를 정렬한 다음, 두 개의 정렬된 부분 리스트를 합하여 전체가 정렬된 리스트가 되게 하는 방법이다.
합병 정렬은 다음의 단계들로 이루어진다.
/* 병합 정렬 프로그램 */
#include <stdio.h>
#include <stdlib.h>
static int *buff; /* 작업용 배열 */
/*--- 병합 정렬(main 부분) ---*/
static void __mergesort(int a[], int left, int right)
{
if (left < right) {
int center = (left + right) / 2;
int p = 0;
int i;
int j = 0;
int k = left;
__mergesort(a, left, center); /* 앞부분에 대한 병합 정렬 */
__mergesort(a, center + 1, right); /* 뒷부분에 대한 병합 정렬 */
for (i = left; i <= center; i++)
buff[p++] = a[i];
while (i <= right && j < p)
a[k++] = (buff[j] <= a[i]) ? buff[j++] : a[i++];
while (j < p)
a[k++] = buff[j++];
}
}
/*--- 병합 정렬 함수 ---*/
int mergesort(int a[], int n)
{
if ((buff = calloc(n, sizeof(int))) == NULL)
return -1;
__mergesort(a, 0, n - 1); /* 배열 전체를 병합 정렬 */
free(buff);
return 0;
}
int main(void)
{
int i, nx;
int *x; /* 배열의 첫 번째 요소에 대한 포인터 */
puts("병합 정렬");
printf("요소 개수 : ");
scanf("%d", &nx);
x = calloc(nx, sizeof(int));
for (i = 0; i < nx; i++) {
printf("x[%d] : ", i);
scanf("%d", &x[i]);
}
mergesort(x, nx); /* 배열 x를 병합 정렬 */
puts("오름차순으로 정렬했습니다.");
for (i = 0; i < nx; i++)
printf("x[%d] = %d\n", i, x[i]);
free(x); /* 배열을 해제 */
return 0;
}
배열 병합의 시간 복잡도 : O(n)
병합 정렬의 단계는 log n 만큼 필요
전체 시간 복잡도 : O(n log n)
서로 떨어져 있는 요소를 교환하는 것이 아니므로 안정적인 정렬 방법