1. 程式人生 > 實用技巧 >二路歸併排序

二路歸併排序

思路總結

  1. 先將n個記錄兩兩分組
    • 若n為奇數也沒關係,1個記錄的組不需要進行比較,回到遞迴上一層會進行3個記錄的merge
  2. 分組完成後,進行兩兩合併merge,merge中進行排序
    • 因為兩個需要合併的陣列都是有序的,所以不需要O(nlogn)的排序方法,進行O(n)的比較排序即可
    • merge中需要輔助陣列,儲存排序過程

注意

  1. 時間複雜度O(nlogn),n個記錄,需要logn趟twoWayMerge,每趟中的merge需要n-1次比較
  2. 空間複雜度O(n)
  3. 穩定演算法

程式碼

#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int>& v, int l, int mid, int r) {
	vector<int> temp(r - l + 1);
	int i = l, j = mid + 1, tempIndex=0;
	while (i <= mid && j <= r) {
		if (v[i] <= v[j]) temp[tempIndex++] = v[i++];
		else temp[tempIndex++] = v[j++];
	}
	while (i <= mid) temp[tempIndex++] = v[i++];
	while (j <= r) temp[tempIndex++] = v[j++];
	for (i = l, tempIndex=0; i <= r; i++,tempIndex++) {
		v[i] = temp[tempIndex];
	}
}
void twoWayMerge(vector<int>& v, int l, int r) {
	if (l == r) return;
	else {
		int mid = (l + r) >> 1;
		twoWayMerge(v, l, mid);
		twoWayMerge(v, mid + 1, r);
		merge(v, l, mid, r);
	}
}
int main() {
	vector<int> v = { 49,38,65,97,76,13,27,49 };
	twoWayMerge(v,0,v.size()-1);
	for (auto a : v) cout << a << " ";
	cout << endl;

	return 0;
}