- merge sort




- 분할 정복(divide and conquer) 방법, 보통 재귀를 이용하여 구현

- 분할(divide): 입력 배열을 같은 크기의 2개의 부분 배열로 분할한다.
  정복(conquer): 부분 배열을 정렬한다. 부분 배열의 크기가 충분히 작지 않으면 순환 호출을 이용하여 다시 분할 정복 방법 적용
  결합(combine): 정렬된 부분 배열들을 하나의 배열에 합병

- 시간복잡도 분석
 : 배열이 부분 배열로 나누어지는 단계에서는 비교 연산이나 이동 연산이 수행되지 않는다. 재귀 호출의 깊이는 

 : 합병단계에서 비교 연산 최대 n번, 임시 배열에 복사했다가 다시 가져와야하는 이동 연산 n 번으로 총 2n번 레코드의 이동 발생
 : 총 시간 복잡도는 

- 입력 데이터가 무엇이든 간에 정렬되는 시간은 동일 (데이터의 분포에 영향을 덜 받는 안정적인 정렬 방법)

- 단점으로

  : 임시 배열이 필요함
  : 레코드들의 크기가 큰 경우에는 이동 횟수가 많으므로 매우 큰 시간적 낭비를 초래 -> 연결리스트로 극복


- CODE

#include <iostream>
using namespace std;

int arr[1000001];
int save[1000001];

void merge_sort(int* a, int start, int end) {
	if (start == end) {
		return;
	}
	else if (start + 1 == end) {
		if (a[start] > a[end]) {
			swap(a[start], a[end]);
		}
		return;
	}

	// divide
	int mid = (start + end) / 2;
	merge_sort(a, start, mid);
	merge_sort(a, mid + 1, end);
	int left = start;
	int right = mid + 1;
	int k = 0;

	// conquer
	while (left <= mid && right <= end) {
		if (a[left] <= a[right]) {
			save[k++] = a[left++];
		}
		else {
			save[k++] = a[right++];
		}
	}
	while (left <= mid) {
		save[k++] = a[left++];
	}
	while (right <= end) {
		save[k++] = a[right++];
	}

	// combine
	for (int i = start; i <= end; i++) {
		a[i] = save[i - start];
	}
}

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> arr[i];
	}

	merge_sort(arr, 0, n - 1);

	for (int i = 0; i < n; i++)
		cout << arr[i] << "\n";

	return 0;
}


'Algorithm' 카테고리의 다른 글

알고리즘 - 힙 정렬  (0) 2015.11.12
알고리즘 - 퀵 정렬  (0) 2015.11.12
알고리즘 - 셸 정렬  (0) 2015.11.12
알고리즘 - 버블 정렬  (0) 2015.11.12
알고리즘 - 삽입 정렬  (0) 2015.11.12

+ Recent posts