자료구조
[알고리즘]합병 정렬(merge sort).
khoneybee
2021. 12. 6. 18:24
합병 정렬은 분할 정복이라는 알고리즘 디자인 기법에 근거하여 만들어진 정렬방법이다.
이 과정을 3가지 과정으로 나누어서 보면
1. 분할: n개의 데이터를 더이상 쪼갤 수 없을 때까지 분할한다.
2. 정복: 분할된 문제를 해결한다.(정렬)
3. 결합: 분할해서 해결한 결과를 결합한다.
이렇게 나눌 수 있다.
이번 시간에는 정수의 오름차순을 기준으로 하여 합병 정렬을 설명하겠다.
먼저 이해를 돕기 위해서 아래 그림을 참고해라.
이 과정을 코드로 나태내기 위해서는 분할을 담당하는 함수, 정복 및 병합을 담당하는 함수 2가지가 필요하다.
먼저 분할을 담당하는 함수를 살펴보자.
void mergeSort(int arr[], int first, int last)
{
int mid;
if (first < last) //분할할 수 있으면
{
mid = (first + last) / 2; //중간지점을 계산.
//둘로 나눠서 각각을 정렬.
mergeSort(arr, first, mid);
mergeSort(arr, mid + 1, last);
//정렬된 두 배열을 병합(자세한 설명은 다음 코드로)
merge(arr, first, mid, last);
}
}
다음으로 정복 및 병합을 담당하는 함수를 살펴보자.
분할된 배열을 효율적으로 정렬하기 위해서는 또 다른 배열이 필요하기에 동적할당을 하여 배열을 만들었다.
void merge(int arr[], int first, int mid, int last) //정복 및 결합
{
int* tArr = (int*)malloc(sizeof(int) * (last + 1));
int left = first;
int right = mid + 1;
int tIdx = first; //배열의 시작부분
while (left <= mid && right <= last) //left가 mid를 넘어서거나 right가 last를 넘어설 때까지 반복.
{
if (arr[left] > arr[right])
{
tArr[tIdx] = arr[right++];
}
else
{
tArr[tIdx] = arr[left++];
}
tIdx++;
}
if (left > mid) //왼쪽 배열을 다 썻으면
{
while (right <= last) //오른쪽의 나머지 배열을 삽입.
{
tArr[tIdx] = arr[right++];
tIdx++;
}
}
else
{
while (left <= mid)
{
tArr[tIdx] = arr[left++];
tIdx++;
}
}
//tArr에 정렬된 배열을 arr에 삽입.
for (int i = first; i <= last; i++)
{
arr[i] = tArr[i];
}
//동적할당 해제
free(tArr);
}
전체 코드
#include <stdio.h>
#include <stdlib.h>
void merge(int arr[], int first, int mid, int last)
{
int* tArr = (int*)malloc(sizeof(int) * (last + 1));
int left = first;
int right = mid + 1;
int tIdx = first;
while (left <= mid && right <= last)
{
if (arr[left] > arr[right])
{
tArr[tIdx] = arr[right++];
}
else
{
tArr[tIdx] = arr[left++];
}
tIdx++;
}
if (left > mid)
{
while (right <= last)
{
tArr[tIdx] = arr[right++];
tIdx++;
}
}
else
{
while (left <= mid)
{
tArr[tIdx] = arr[left++];
tIdx++;
}
}
for (int i = first; i <= last; i++)
{
arr[i] = tArr[i];
}
free(tArr);
}
void mergeSort(int arr[], int first, int last)
{
int mid;
if (first < last)
{
mid = (first + last) / 2;
mergeSort(arr, first, mid);
mergeSort(arr, mid + 1, last);
merge(arr, first, mid, last);
}
}
int main(void)
{
int arr[] = { 8, 5, 1, 3, 7, 2, 6, 9 };
mergeSort(arr, 0, 7);
for (int i = 0; i < 8; i++)
{
printf("%d ", arr[i]);
}
return 0;
}