더이상 나누어지지 않을 때까지 요소를 반으로(균등하게) 쪼갠 후, 다시 합병시키면서 정렬해나가는 방식. 합병의 대상이 되는 두 영역이 각 영역에 대해서 이미 정렬이 되어있기 때문에 단순히 두 배열을 순차적으로 비교하면서 정렬
- 퀵정렬 : 우선 피벗을 통해 정렬(partition) → 영역을 쪼갬(quickSort)
- 합병정렬 : 영역을 쪼갤 수 있을 만큼 쪼갬(mergeSort) → 정렬(merge)
분할 정복(Divide and Conquer) 전략
안정 정렬(stable)
정렬 과정에서 추가적인 리스트 필요
- 2개의 리스트의 값들을 처음부터 하나씩 비교하여 두 개의 리스트의 값 중에서 더 작은 값을 새로운 리스트(sorted)로 옮김
- 둘 중에서 하나가 끝날 때까지 이 과정을 되풀이한다.
- 만약 둘 중에서 하나의 리스트가 먼저 끝나게 되면 나머지 리스트의 값들을 전부 새로운 리스트(sorted)로 복사한다.
- 새로운 리스트(sorted)를 원래의 리스트(list)로 옮긴다.
코드
#include<iostream>
using namespace std;
int N,arr[1000001];
int *arr2;
void merge(int left, int right)
{
int mid = (left + right) / 2;
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right)
{
if (arr[i] <= arr[j])
arr2[k++] = arr[i++];
else
arr2[k++] = arr[j++];
}
int tmp = i>mid ? j : i;
while(k<=right) arr2[k++] = arr[tmp++];
for (int i=left;i<=right;i++) arr[i] = arr2[i];
}
void partition(int left,int right)
{
int mid;
if (left < right)
{
mid = (left + right) / 2;
partition(left, mid);
partition(mid + 1, right);
merge(left, right);
}
}
int main()
{
scanf("%d",&N);
arr2 = new int[N];
for (int i=0;i<N;i++) scanf("%d",&arr[i]);
partition(0, N - 1);
for (int i=0;i<N;i++) printf("%d\n",arr[i]) ;
}
시간복잡도
시간복잡도 | |
---|---|
최선 | Ω(nlog(n)) |
평균 | Θ(nlog(n)) |
최악 | O(nlog(n)) |
=>합병 단계에서 nlogn
O(n)