歸併排序算法

思路:把待排序序列分成相同大小的兩個部分,依次對這兩部分進行歸併排序,完畢之後再按照順序進行合併。具體思路請參考算法導論,以下實現按算法導論中思路來寫的。

性能:穩定的排序算法,時間複雜度最差、平均、最好都是O(nlogn),空間複雜度爲O(n)。

實現1:遞歸實現


#include <iostream>
using namespace std;

void mergeSort(int a[], int p, int r);
void merge(int a[], int p, int q, int r);

void mergeSort(int a[], int p, int r)
{
	int q;

	q = (p+r)/2; //分成兩部分
	if(p < r){
		mergeSort(a, p, q);
		mergeSort(a, q+1, r);
		merge(a, p, q, r);
	}
}

void merge(int a[], int p, int q, int r)
{
	int n1 = q-p+1; //左邊元素個數
	int n2 = r-q;	//右邊元素個數
	int i, j, k;
	int L[n1], R[n2];

	for(i = 0; i < n1; i++)
		L[i] = a[p+i]; //左邊元素拷貝到L中
	for(j = 0; j < n2; j++)
		R[j] = a[q+1+j]; //右邊元素運拷貝到R中

	i = j = 0;
	k = p;
	while(i < n1 && j < n2){
		if(L[i] <= R[j])
			a[k] = L[i++];
		else
			a[k] = R[j++];
		k++;
	}

	while(i < n1)
		a[k++] = L[i++];
	while(j < n2)
		a[k++] = R[j++];
}

int main()
{
	int a[8] = {1002, 6, 5, 4, 1, 10, 11, 6};
	mergeSort(a, 0, 7);

	for(int i = 0; i < sizeof(a)/sizeof(int); i++)
		cout << a[i] << " ";
	cout << endl;

	return 0;
}

實現2:循環實現

思路:給定數組{23, 10, 8, 5, 7, 21, 18},首先步長爲2,分成段23 10、8 5、7 21、18四段,最後一段只有一個元素。首先分段歸併10 23、5 8、7 21、18等,再次步長爲4,分成10 23 5 8、7 21 18兩段,注意第二段只有3個元素,3 > step/2,因爲上次的循環步長爲step/2,最後一段中的前step/2個元素一定有序的,後面幾個不一定了。因此最後段歸併時,注意找好這個點進行歸併。再最後一次步長爲8,進行歸併。

#include <iostream>
using namespace std;

void merge(int a[], int p, int q, int r);

/* 歸併排序算法循環實現 */
void mergeSort(int a[], int n)
{
	if(a == NULL || n <= 0) 
		return;
	for(int step = 2; step/2 < n; step *= 2){ //步長:2,4,8,16...,結束條件是步長
		for(int i = 0; i < n; i += step){ //每一段
			int start = i; //段首
			int end = i + step - 1; //段尾
			if(i + step < n){ //最後一段可能出現元素不夠的情況
				int mid = (start + end) / 2;
				merge(a, start, mid, end);
			}
			else{ //如果最後一次,元素個數不夠夠一整段
				if(i + step/2 -1 >= n-1) //如果夠一半,這一半一定是有序的
					break;
				merge(a, i, i + step/2 - 1, n - 1);
			}
		}
	}
}

/* 合併兩個數組 */
void merge(int a[], int p, int q, int r)
{
	int n1 = q - p + 1;
	int n2 = r - q;
	int *c1 = new int[n1];
	int *c2 = new int[n2];
	for(int i = 0; i < n1; i++)
		c1[i] = a[p + i];
	for(int i = 0; i < n2; i++)
		c2[i] = a[q + 1 + i];

	int i = 0, j = 0, k = p;
	while(i < n1 && j < n2){
		if(c1[i] <= c2[j])
			a[k++] = c1[i++];
		else
			a[k++] = c2[j++];
	}
	if(i < n1){
		while(i < n1)
			a[k++] = c1[i++];
	}

	if(j < n2){
		while(j < n2)
			a[k++] = c2[j++];
	}

	delete c1, c2;
}

int main()
{
//	int a[] = {23}; // 1
//	int a[] = {2, 10};
//	int a[] = {10, 2};
//	int a[] = {10, 2, 11};
//	int a[] = {11, 10, 2};
//	int a[] = {12, 10, 15, 13};
//	int a[] = {12, 10, 15, 11};
//	int a[] = {23, 10, 8, 5, 7};
//	int a[] = {23, 10, 8, 5, 7, 21};
//	int a[] = {23, 10, 8, 5, 7, 21, 100};
	int a[] = {23, 10, 8, 5, 7, 21, 18, 100};
	int n = sizeof(a)/sizeof(int);
	mergeSort(a, n);
	for(int i = 0; i < n; i++)
		cout << a[i] << " ";
	cout << endl;
	return 0;
}


發佈了50 篇原創文章 · 獲贊 16 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章