Game Programming/알고리즘
[알고리즘] 병합 정렬 (Merge Sort)
Doanie
2022. 9. 21. 14:44
[알고리즘] 병합 정렬 (Merge Sort)
병합정렬은 퀵정렬과 마찬가지로 분할 정복 방법의 알고리즘이며 퀵정렬과 마찬가지로 O(N * logN)의 시간 복잡도를 가진다.
먼저 반을 나누고 나중에 합쳐서 정렬을 하자!!!!
다음 숫자들을 오름차순으로 정렬하는 프로그램을 작성하자!
7, 10, 5, 8, 1, 6, 3, 4, 2, 9
7 10 5 8 1 | 6 3 4 2 9 //반 나누기
7 10 5 | 8 1 | 6 3 4 | 2 9 //나눈 것을 또 나누기
5 7 10 | 1 8 | 3 4 6 | 2 9 //나눠진 것들 정렬
1 5 7 8 10 | 2 3 4 6 9 //합쳐서 정렬
1 2 3 4 5 6 7 8 9 10
소스코드 구현 (C++)
#include <iostream>
//정렬될 배열을 미리 전역변수로 선언해두자
int Sorted[9999];
void Merge(int* data, int start, int middle, int end)
{
int i = start;
int j = middle + 1;
int index = start;
//작은 순서대로 배열에 삽입
while (i <= middle && j <= end)
{
//앞에것이 작으면 앞에것을 넣어주기
if (data[i] <= data[j])
{
Sorted[index] = data[i];
i++;
}
//뒤에것이 같거나 크다면 뒤에것을 넣어주기
else
{
Sorted[index] = data[j];
j++;
}
index++;
}
//남은 데이터 넣기
if (i > middle)
{
for (int k = j; k <= end; k++)
{
Sorted[index] = data[k];
index++;
}
}
else
{
for (int k = i; k <= middle; k++)
{
Sorted[index] = data[k];
index++;
}
}
//정렬된 배열을 삽입
cout << "[";
for (int k = start; k <= end; k++)
{
data[k] = Sorted[k];
cout << data[k] << " ";
}
cout << "]" << endl;
}
void MergeSort(int* data, int start, int end)
{
//크기가 1보다 큰 경우
if (start < end)
{
int middle = (start + end) / 2;
MergeSort(data, start, middle);
MergeSort(data, middle + 1, end);
Merge(data, start, middle, end);
}
}
int main()
{
int temp;
int arr[10] = { 1, 10, 5, 8, 7, 6, 3, 4, 2, 9 };
//병합 정렬
MergeSort(arr, 0, 9);
//출력
for (int i = 0; i < 10; i++)
{
cout << arr[i] << ", ";
}
return 0;
}
시간 복잡도 계산
일단 데이터를 반으로 나누어서 정렬하기 때문에 logN이며, 또한 나누어진것은 이미 정렬이 되어있는 것이고 이것을 또 정렬하기 때문에 N이다. 즉, 이 두개를 합친 N * logN이 되는 것이다.
병합 정렬은 시작점이 아니라 처음부터 반으로 나누면서 시작하기 때문에 O(N * logN)의 시간복잡도를 보장한다. 하지만 기존의 데이터를 담을 추가적인 공간이 필요하며 이것을 전역변수로 선언하여서 사용하였다. 그렇기 때문에 시작복잡도를 보장한다는 장점이 있지만 메모리 활용이 비효율적이라는 문제가 있습니다.