【排序算法】 ——— 归并排序总结

归并排序是一种基于分治思想的排序算法,通过递归将数据序列不断分割成小的子序列,再进行有序合并,最终得到完全有序的序列。其时间复杂度为O(NlogN),空间复杂度为O(N),是稳定的排序方法。在实际应用中,归并排序的性能受到元素比较和数组移动开销的影响。
摘要由CSDN通过智能技术生成

【1】归并排序的思想

"归并"一词的中文含义就是合并、并入的意思,而在数据结构中的定义是将两个或两个以上的有序表组合成一个新的有序表。

归并排序(Merging Sort) 就是利用归并的思想实现的排序方法

原理是:假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2] 个长度为2或1的有序子序列;再两两归并, … 如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为二路归并排序,也就是归并排序

归并排序是利用递归与分治的技术将数据序列划分为越来越小的半子表,再对半子表排序,最后再用递归方法将排好序的半子表合并成越来越大的有序序列。

假设现在要对数组{50,10,90,30,70,40,80,60,20}进行排序,数组长度为9,我们来看看是怎么排序的

在这里插入图片描述
【1】我们找到中间位置5,从这里分开分成两组,再继续分割分成四组,依次分割直到不可分割如下图所示
在这里插入图片描述【2】分割完成之后再依次对部分进行按序合并如下图所示
在这里插入图片描述

接下来我们从代码的具体实现来仔细体会其中的思路

【2】代码示例

#include<iostream>
void Merge(int sourceArr[], int tempArr[], int startIndex, int midIndex, int endIndex)
{
	int i = startIndex, j = midIndex + 1, k = startIndex;
	//从中间分开 i++一直到midindex,j++一直到到endindex
	while (i != midIndex + 1 && j != endIndex + 1)	
	{
		//分别比较两组数据对应位置的数字的大小,找出小的数字,放入辅助数组
		if (sourceArr[i] > sourceArr[j])
			tempArr[k++] = sourceArr[j++];
		else
			tempArr[k++] = sourceArr[i++];
	}
	//当把其中一个数组的数全部放入辅助数组后将剩余下的另外一个数组中的元素全部依次放入辅助数组
	while (i != midIndex + 1)	//判断是哪个部分还剩余数字
		tempArr[k++] = sourceArr[i++];
	while (j != endIndex + 1)
		tempArr[k++] = sourceArr[j++];
	//将辅助数组中的元素全部导入原数组中
	for (i = startIndex; i <= endIndex; i++)
		sourceArr[i] = tempArr[i];	
}

//内部使用递归
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex)
{
	int midIndex;
	if (startIndex < endIndex)	//分割到剩两个元素或者一个元素则再也不可分割,分组完成
	{	
		//找到中间位置进行分治
		midIndex = startIndex + (endIndex - startIndex) / 2;	//避免溢出int
		//分别对分割开的部分进行递归分割
		MergeSort(sourceArr, tempArr, startIndex, midIndex);
		MergeSort(sourceArr, tempArr, midIndex + 1, endIndex);
		//将分割开的数组进行合并
		Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
	}
}

int main()
{
	int a[8] = { 50, 10, 20, 30, 70, 40, 80, 60 };
	int i, b[8];
	MergeSort(a, b, 0, 7);
	for (i = 0; i < 8; i++)
	{
		cout << a[i]<<" ";
	}	
	cout << endl;
	return 0;
}

【3】时间复杂度

空间效率:在merge()操作中,辅助空间刚好要占用n个单元,所以归并排序的的空间复杂度为O(n)

时间效率:每一趟归并的时间复杂度为O(n),共需要进行 logN 趟排序,所以时间复杂度为 O(NlogN)

稳定性:因为merge()操作不会改变相同关键字记录的相对次序,所以是一个稳定的排序方法

深入分析:
虽然归并排序的运行时间是 O(NlogN) ,但他有一个明显的问题,即合并两个已排序的表用到线性附加内存,在整个算法中还要花费将数据拷贝到临时数组再拷贝回来这些附加的工作,他明显减慢了排序的速度与其他的 O(NlogN) 排序算法比较,归并排序的运行时间严重依赖于比较元素和在数组(以及临时数组)中移动元素的相对开销

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值