排序算法:归并排序

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。


例如,有两组有序数据,我们可以通过如下方式(以下简称归并排序)让两组数据快速有序

我们可以依次从两组中取最前的那个最小元素依次有序放到新的数组中,然后再把新数组中有序数据拷贝到园数组中,快速完成排序。

 


 依靠这种思路,再结合分而治之的思想来实现归并排序

具体步骤

对于下面一组待排序数组

先以中间为界,把其均分为A和B两个数组(如果是奇书个,允许两组数相差一个)

如果A和B两组数据能够有序,则我们可以通过上面的方式让数组快速排好序。

        此时,A组有4个成员,B组有5个成员,但两个数组都无序,然后我们可以采用分治法继续对AA组和B组进行均分,以A组为例,又可以均分A1和A2两个组如下:

        均分后,A1 组和 A2 组仍然无序,继续利用分治法细分,以 A1 组为例,A1 又可分成如下
两组。

         数组细分到一个元素后,这时候,我们就可以采用归并法借助一个临时数组将数组 A1 有序化!A2 同理!

 依次类推,将 A1 组和 A2 组归并成有序的 A 组, B 组同理!

 最后,将 A 和 B 组使用归并大法合并,就得到了完整的有序的结果!

 

归并排序算法图示: 

程序实现

#include<iostream>
using namespace std;

void mergeAdd(int* a, int begin, int middle, int end,int *b) {
	int index = begin;
	int left = begin;
	int right = middle;
	while (left <= middle - 1 && right <= end) 
		b[index++] = (a[left] > a[right] ? a[right++] : a[left++]);//取小值
	while (left <= middle - 1)
		b[index++] = a[left++];
	while (right <= end)
		b[index++] = a[right++];
	memcpy(a+begin, b+begin, sizeof(int) * (end - begin + 1));
}

void mergeSort(int* a, int begin, int end, int* b){
	if (end > begin) {
		int index = begin + (end - begin) / 2;
		mergeSort(a, begin, index,b);
		mergeSort(a, index+1, end, b);
		mergeAdd(a, begin, index+1, end, b);
	}
}

int main() {


	int a[] = {163,161,158,165,171,170,163,159,162};
	int len = sizeof(a) / sizeof(int);
	int* b = new int[len];
	int middle = len / 2;
	mergeSort(a, 0, len - 1,b);

	for (int i = 0; i < len; i++)
		cout << a[i] << endl;

	system("pause");
	return 0;
}

运行结果  

平均时间复杂度: O( n * log n)

最好情况:O(n * log n)

最坏情况:O(n * log n)

排序方式:Out-place

稳定性:稳定

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值