归并排序算法

思路:把待排序序列分成相同大小的两个部分,依次对这两部分进行归并排序,完毕之后再按照顺序进行合并。具体思路请参考算法导论,以下实现按算法导论中思路来写的。

性能:稳定的排序算法,时间复杂度最差、平均、最好都是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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章