-
5. 분할과 정복_병합정렬(Merge Sort)Algorithm 2019. 10. 4. 02:02
#분할과 정복을 이용한 정렬
-병합정렬
-퀵정렬
#분할과 정복 알고리즘
1. 큰 문제를 작은 문제들로 나눈다.
2. 단계1의 작은 문제들의 해를 재귀적으로 구한다.
3. 단계2에서 구한 작은 문제들의 해를 이용하여 원래 문제의 해를 구한다.
#병합정렬 알고리즘
1. 주어진 크기가 n인 리스트를 크기가 n/2인 두 부분으로 나눈다.
2. 크기가 n/2인 두 부분을 재귀적으로 정렬한다.
3. 정렬된 두 부분을 하나로 병합한다.
merge sort #구현
#include <iostream> using namespace std; int* sorted; void mergesort(int a[], int first, int last); void merge(int a[], int first, int mid, int last); int main(){ int size; cin>>size; sorted = new int[size]; //정렬 후 배열 int* a = new int[size]; //정렬 전 배열 for(int i=0; i<size; i++) cin>>a[i]; mergesort(a,0,size-1); for(int i=0; i<size; i++) cout<<a[i]<<" "; delete[] a; return 0; } void mergesort(int a[], int first, int last){ if(first<last){ int mid=(first+last)/2; mergesort(a,first,mid); mergesort(a,mid+1,last); merge(a,first,mid,last); } } void merge(int a[], int first, int mid, int last){ int i=first; //왼쪽 배열의 첫 번째 인덱스 int j=mid+1; //오른쪽 배열의 첫 번째 인덱스 int k=first; //sorted의 첫 번째 인덱스 //두 집합의 원소들 비교해서 더 작은 원소를 sorted 배열에 넣기 while(i<=mid && j<=last){ if(a[i]<=a[j]){ sorted[k]=a[i]; i++; } else{ sorted[k]=a[j]; j++; } } //남은 원소 sorted에 넣기 if(i>mid){ //오른쪽 원소는 모두 sorted에 담긴 상태 for(int t=j; t<=last; t++){ sorted[k]=a[t]; k++; } } else{ //왼쪽 원소는 모두 sorted에 담긴 상태 for(int t=i; t<=mid; t++){ sorted[k]=a[t]; k++; } } for(int t=first; t<=last; t++) a[t]=sorted[t]; }
#시간복잡도
n=1인 경우 -> T(n) = 0
n>1인 경우 -> T(n) ≤ 2T(n/2) + n
≤ 2( 2T(n/4) + n )+n
...
≤ (2^k)T(n/(2^k)) + k*n
즉, n=2^k 일 경우, T(n) ≤ n*T(1) + (log n)*n = 0 + n log n
크기가 n인 배열을 분할할 때 원소가 하나가 될때까지 반으로 나누기 때문에 log n의 시간이 들고,
병합할 때 while을 통해 모든 원소를 비교하기 때문에 n의 시간이 든다.
따라서 병합정렬의 시간복잡도는 T(n): O(n log n) 이다.
#병합정렬의 단점
- 병합할 때 O(n) 추가적인 메모리가 필요하다.(in-place가 아니다)
- O(log n)의 스택 메모리가 필요하다.
'Algorithm' 카테고리의 다른 글
7. 힙 정렬(Heap Sort) (0) 2019.10.16 6. 분할과 정복_퀵정렬(Quick Sort) (0) 2019.10.04 4. 삽입 정렬(Insertion Sort) (0) 2019.10.04 3. 버블 정렬(Bubble Sort) (0) 2019.10.04 2. 선택 정렬(Selection Sort) (0) 2019.10.04