排序篇(四)----归并排序

news2025/1/4 17:08:11

排序篇(四)----归并排序

1.归并(递归)

基本思想:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并排序核心步骤:

在这里插入图片描述
在这里插入图片描述

//归并
void _MergeSort(int* a, int* tmp, int begin, int end)
{
	if (end <= begin)
	{
		return;
	}
	int mid = (begin + end) / 2;
	_MergeSort(a, tmp, begin, mid);
	_MergeSort(a, tmp, mid + 1, end);
	// a->[begin, mid][mid+1, end]->tmp
	//归并
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int index = begin;

	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[index++] = a[begin1++];
		}
		else
		{
			tmp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}
//归并(递归版)
void MergeSort(int* a, int n)
{
	int* tmp = malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	_MergeSort(a, tmp, 0, n - 1);
	free(tmp);
}

​ 归并需要开一个同样大的tmp数组来存放数据,相当于是拿空间来换时间了.

代码详解:

  1. 首先,将整个序列分为两部分,分别递归调用_MergeSort函数对左右两部分进行排序。
  2. 在_MergeSort函数中,首先判断递归终止条件,如果end小于等于begin,则表示当前子序列只有一个元素或者为空,无需排序,直接返回。
  3. 然后,计算中间位置mid,并分别递归调用_MergeSort函数对左右两部分进行排序。
  4. 接下来,进行归并操作。首先,设置四个指针begin1、end1、begin2、end2分别指向左右两部分的起始和结束位置,以及一个指针index指向当前归并结果的位置。
  5. 然后,使用两个循环比较左右两部分的元素大小,并将较小的元素放入tmp数组中,同时移动相应的指针。
  6. 最后,将剩余的元素复制到tmp数组中。
  7. 最后,将tmp数组中的元素复制回原数组a中,完成归并排序。

2.归并(非递归)

​ 非递归版是在递归上进行了修改,将其递归改为了循环.

//归并(非递归版)
void _MergeSortNotR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			if (begin2 >= n)
			{
				break;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}

			int index = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] <= a[begin2])
				{
					tmp[index++] = a[begin1++];
				}
				else
				{
					tmp[index++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[index++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[index++] = a[begin2++];
			}
			memcpy(a+i, tmp+i, (end2-i+1) * sizeof(int));
		}
		gap *= 2;
	}
	free(tmp);
}

代码详解:

​ 分配一个临时数组tmp,用于存储归并结果。

​ 然后,设置一个变量gap为1,表示归并的间隔大小。

接下来,循环执行以下操作,直到gap大于等于n:

  1. 遍历整个数组,每次取两个相邻的子序列进行归并。
  2. 计算左右两个子序列的起始和结束位置。
  3. 判断右子序列的结束位置是否超过了数组的长度,如果超过,则将结束位置设置为数组的最后一个元素的下标。
  4. 使用两个指针begin1和begin2分别指向左右两个子序列的起始位置,使用指针end1和end2分别指向左右两个子序列的结束位置。
  5. 使用一个指针index指向当前归并结果的位置。
  6. 使用一个循环,比较左右两个子序列的元素大小,并将较小的元素放入临时数组tmp中,同时移动相应的指针。
  7. 如果左子序列还有剩余元素,则将剩余元素复制到tmp数组中。
  8. 如果右子序列还有剩余元素,则将剩余元素复制到tmp数组中。
  9. 将tmp数组中的元素复制回原数组a中。
  10. 将gap乘以2,进行下一轮归并。

最后,释放临时数组tmp的内存空间。

归并排序的特性总结:

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
    中的元素复制回原数组a中。
  4. 将gap乘以2,进行下一轮归并。

最后,释放临时数组tmp的内存空间。

归并排序的特性总结:

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1053946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】UDP的服务端 + 客户端

文章目录 &#x1f4d6; 前言1. TCP和UDP2. 网络字节序2.1 大小端字节序&#xff1a;2.2 转换接口&#xff1a; 3. socket接口3.1 sockaddr结构&#xff1a;3.2 配置sockaddr_in&#xff1a;3.3 inet_addr&#xff1a;3.4 inet_ntoa&#xff1a;3.5 bind绑定&#xff1a; 4. 服…

【VR】【unity】如何在VR中实现远程投屏功能?

【背景】 目前主流的VD应用,用于娱乐很棒,但是用于工作还是无法效率地操作键鼠。用虚拟键盘工作则显然是不现实的。为了让自己的头显能够起到小面积代替多显示屏的作用,自己动手开发投屏VR应用。 【思路】 先实现C#的投屏应用。研究如何将C#投屏应用用Unity 3D项目转写。…

FFmpeg 命令:从入门到精通 | ffplay 播放控制选项

FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项选项表格图片 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 播放控制选项 选项表格 项目说明Q&#xff0c;Esc退出播放F&#xff0c;鼠标左键双击全…

计算机网络分层结构

一、OSI参考模型(法定标准) 1.由国际标准化组织(ISO)提出的开放系统互连(OSI)参考模型 2.OSI七层结构&#xff1a; 3.通信过程&#xff1a; 4.各层功能 应用层-能和用户交互产生网络流量(需要联网)的程序&#xff0c;常见协议有文件传输(FTP)、电子邮件(SMTP)、万维网(HTTP)…

MASM32配置问题

1. 总述 当你用masm32 SDK出现类似下面的错误情况: cannot open file :windows.inc这说明你的汇编器无法找到windows.inc这个头文件, 有3种解决方法 2. 解决方法 a. 使用绝对路径 直接把需要的inc头文件或者lib库文件的绝对路径包含进去, 问题就解决了 .586 .model flat,…

【Java 进阶篇】MySQL多表关系详解

MySQL是一种常用的关系型数据库管理系统&#xff0c;它允许我们创建多个表格&#xff0c;并通过各种方式将这些表格联系在一起。在实际的数据库设计和应用中&#xff0c;多表关系是非常常见的&#xff0c;它能够更好地组织和管理数据&#xff0c;实现数据的复杂查询和分析。本文…

Heptabase 究竟好在哪儿?

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; Heptabase 1.0 正式版发布&#xff0c;你可以免费尝试了。 赞誉 我因为研究各种知识管理工具&#xff0c;常年混迹在不同的社区、群组与论坛中…

Python日期的加减等操作

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 日期输出格式化 所有日期、时间的api都在datetime模块内。 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都…

《MySQL高级篇》十六、主从复制

文章目录 1、主从复制概述1.1 如何提升数据库并发能力1.2 主从复制的作用 2、主从复制的原理2.1 原理剖析2.2 复制的基本原则 3、一主一从架构搭建3.1 准备工作3.2 主机配置文件3.3 从机配置文件3.4 主机&#xff1a;建立账户并授权3.5 从机&#xff1a;配置需要复制的主机3.6 …

UE5.1编辑器拓展【二、脚本化资产行为,快速更改资产名字,1.直接添加前缀或后缀2.通过资产类判断添加修改前缀】

目录 了解相关的函数 第一种做法&#xff1a;自定义添加选择资产的前缀或后缀 代码 效果 第二种做法&#xff1a;通过映射来获取资产类型添加前缀和修改前缀 映射代码 代码 效果 在之前一章中&#xff0c;我们创建了插件&#xff0c;用来扩展编辑器的使用&#xff1a; …

福利!这两款我自制的免费配色工具你领到了吗?

​前两天刚入职&#xff0c;还没干过啥活儿&#xff0c;就迎来了中秋3天国庆7天总共8天的假期&#xff0c;美滋滋。 在这么喜庆的日子里&#xff0c;我觉得大家应该也无心科研&#xff0c;所以不如给大家发点儿福利&#xff0c;继续乐呵乐呵。 当然&#xff0c;说是福利&…

Redis代替session 实现登录流程

Redis代替session 实现登录流程 如果使用String&#xff0c;他的value&#xff0c;用多占用一点空间&#xff0c;如果使用哈希&#xff0c;则他的value中只会存储他数据本身&#xff0c;如果不是特别在意内存&#xff0c;其实使用String就可以 设计key的具体细节 在设计这个k…

如何在Cocos中绘制一面国旗祝祖国生日快乐、繁荣昌盛

引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 74年风雨兼程、74载山河巨变&#xff0c;我们一起来祝福伟大的祖国生日快乐、繁荣昌盛&#xff01;我爱你中国&#xff01; 本文主要演示在Cocos中绘制一面国旗&#xff0c;用代码去表达…

【Java每日一题】— —第十七题:杨辉三角(等腰三角形)。(2023.10.01)

&#x1f578;️Hollow&#xff0c;各位小伙伴&#xff0c;今天我们要做的是第十七题。 &#x1f3af;问题&#xff1a; 第一步:动态初始化 第二步:求各元素的值 第三步:遍历输出 测试结果如下&#xff1a; &#x1f3af; 结果&#xff1a; public class yanghui {public sta…

10.1 国庆节小任务

目录 select实现服务器并发 服务器 客户端 运行现象 select实现服务器并发 服务器 #include<myhead.h>#define PORT 8888 //1024~49151 #define IP "192.168.1.104" //ifconfig查看本机IPint main(int argc, const char *argv[]) {//创建流式…

1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计

项目完整版在&#xff1a; 一、socket模块&#xff1a;套接字模块 二、提供的功能 Socket模块是对套接字操作封装的一个模块&#xff0c;主要实现的socket的各项操作。 socket 模块&#xff1a;套接字的功能 创建套接字 绑定地址信息 开始监听 向服务器发起连接 获取新连接 …

WPF 02

Grid容器 分行和分列 <Grid><Grid.RowDefinitions><!--2*&#xff1a;此行是下面一行的两倍--><RowDefinition Height"2*"/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/>…

[管理与领导-107]:IT人看清职场中的隐性规则 - 4 - 职场话术:其实是同一个意思,只是换一种了说法,效果不同,小心被套路

目录 前言&#xff1a; 一、套路和核心思想 1.1 核心思想 1.2 基本原则&#xff1a;让听话者舒服 二、消极变积极的说法 》 自足当下&#xff0c;展望未来 三、委婉拒绝 四、不想接受某项任务 五、正面、让人舒服的表达方式 六、其他 七、职场话术128条&#xff1a;…

ssm+vue的4S店预约保养管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的4S店预约保养管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

淘宝/天猫获得淘宝商品详情API(含测试示例)

taobao.item_get 调用说明 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中进入测试&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]c…