数据结构|排序算法(三)归并排序

三、归并排序

1.算法思想

归并排序的基本思想是将一个数组分成两个子数组,对每个子数组进行排序,然后将排序好的子数组合并成一个排序好的数组。这个过程是递归进行的,直到子数组的长度为 1,此时子数组已经是有序的。

1.分解:将待排序的数组不断地分成两半,直到每个子数组只有一个元素。可以使用递归实现这一步骤。

2.合并:将两个已经排序好的子数组合并成一个排序好的数组。在合并过程中,比较两个子数组的元素,将较小的元素依次放入一个临时数组中,直到其中一个子数组的元素全部被放入临时数组。然后将另一个子数组中剩余的元素全部放入临时数组。最后将临时数组中的元素复制回原数组。

注意边界越界。

2.代码实现

复制代码
//归并排序
//一次归并
//gap:归并段的长度
static void Merge(int* arr, int len, int gap)
{
	int low1 = 0;//第一个归并段的起始下标
	int high1 = low1 + gap - 1;//第一个归并段的结束下标
	int low2 = high1 + 1;//第二个归并段的起始下标
	int high2 = low2 + gap - 1 < len - 1 ? low2 + gap - 1 : len - 1;//第二个归并段的结束下标//防止越界
	//存放归并好的数据
	int* brr = (int*)malloc(len * sizeof(int));
	assert(brr != NULL);
 
	int i = 0;//brr的下标
	//有两个归并段
	while (low2 < len)//表面至少存在两个归并段
	{
		//两个归并段都有数据,需要比较low1和low2
		while (low1<=high1&&low2<=high2)
		{
			if (arr[low1] <= arr[low2])
			{
				brr[i++] = arr[low1++];
			}
			else
			{
				brr[i++] = arr[low2++];
			}//谁小存谁
		}
		//一个归并段的数据已经完成了,另一个还有数据
		while (low1 <= high1)//第一个归并段还有数据
		{
			brr[i++] = arr[low1++];
		}
		while (low2 <= high2)//第二个归并段还有数据
		{
			brr[i++] = arr[low2++];
		}
		//下两个归并段
		low1 = high2 + 1;
		high1 = low1 + gap - 1;
		low2 = high1 + 1;
		high2 = low2 + gap < len ? low2 + gap - 1 : len - 1;
	}
	//只有一个归并段
	while (low1<len)
	{
		brr[i++] = arr[low1++];
	}
	//将归并好的数据拷贝到arr中
	for (i = 0; i < len; i++)
	{
		arr[i] = brr[i];
	}
	free(brr);
}
 
void MergeSort(int* arr, int len)
{
	for (int i = 1; i < len; i *= 2)
	{
		Merge(arr, len, i);//一次归并
	}
}

3.复杂度分析

归并排序是一种基于分治思想的排序算法:

时间复杂度:

最好情况:当待排序序列已经是有序的时候,归并排序依然需要进行logn层的归并操作,每层归并操作需要比较和移动n次元素,所以时间复杂度为O(nlogn)。

最坏情况:当待排序序列是逆序的时候,同样需要logn层归并操作,每层归并操作也需要比较和移动n次元素,时间复杂度也是O(nlogn)。平均情况:归并排序将序列分成两部分,然后对两部分分别排序,再将排好序的两部分合并。

在平均情况下,每次划分都能将序列分成大致相等的两部分,所以时间复杂度为O(nlogn)。

空间复杂度:归并排序在合并过程中需要借助额外的存储空间来存放临时数据,最坏情况下需要

O(n)的辅助空间来完成排序。

稳定性:归并排序是稳定的排序算法。在归并过程中,当左右两个子序列中出现相等元素时,先将左边子序列中的元素放入临时数组,然后再将右边子序列中的元素放入临时数组,这样相等元素的相对顺序在排序前后不会发生改变。

综上所述,归并排序的时间复杂度为O(nlogn),空间复杂度为O(n),并且是稳定的排序算法。

以上是排序算法第三部分关于选择排序、堆排序以及归并排序的知识,如果有帮助可以点赞收藏一下,会持续更新输出有用的内容,感兴趣可以关注我!

相关推荐
重生之我是Java开发战士8 小时前
【动态规划】简单多状态dp问题:按摩师,打家劫舍,删除并获得点数,粉刷房子,买卖股票的最佳时机
算法·动态规划·哈希算法
KAU的云实验台9 小时前
单/多UAV、静/动态路径规划,基于PlatEMO平台的带约束多目标优化 本文核心内容:
算法·matlab·无人机
Liangwei Lin9 小时前
洛谷 P1807 最长路
数据结构·算法
会编程的土豆9 小时前
【数据结构与算法】二叉树从建立开始
数据结构·c++·算法
_日拱一卒9 小时前
LeetCode:最大子数组和
数据结构·算法·leetcode
计算机安禾9 小时前
【数据结构与算法】第22篇:线索二叉树(Threaded Binary Tree)
c语言·开发语言·数据结构·学习·算法·链表·visual studio code
算法鑫探10 小时前
解密2025数字密码:数位统计之谜
c语言·数据结构·算法·新人首发
计算机安禾10 小时前
【数据结构与算法】第21篇:二叉树遍历的经典问题:由遍历序列重构二叉树
c语言·数据结构·学习·算法·重构·visual studio code·visual studio
信奥胡老师10 小时前
P1255 数楼梯
开发语言·数据结构·c++·学习·算法
爱睡懒觉的焦糖玛奇朵11 小时前
【工业级落地算法之人员摔倒检测算法详解】
人工智能·python·深度学习·神经网络·算法·yolo·目标检测