排序——归并排序

news2024/11/17 13:44:31

文章目录

  • 基本思想
  • 递归版本
    • 思路
    • 代码实现
  • 非递归版
    • 思路
    • 代码实现
  • 结果演示

基本思想

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

递归版本

思路

1.分解:将要排序的序列每次分解为2个序列,直到不能再分解
2.合并:将分解的序列排序并两两归并
在这里插入图片描述
过程:我们需要创建一个临时数组tmp,将每次归并后的结果存入tmp,最后用memcpy将排好后的tmp的数据拷贝到原数组中。

代码实现

void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;//序列只有一个数的时候,不用也不能再分解
	int mid = (begin + end) / 2;
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid+1, end, tmp);//将原序列分解为2段序列
	int i = begin;
	int begin1 = i, end1 = mid;
	int begin2 = mid + 1, end2 = end;//确定两段序列的首位下标
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}//将2段序列中的数按顺序存入tmp
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}//将没存完的那个序列剩下的值(有序)存入tmp
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));//将tmp拷贝给原数组,加上begin定位排序好的值,因为begin是我们操作2个序列的前一个序列的首下标。不加begin的话就是拷贝整个序列的第一个值,可能不是我们正在归并的序列,还没有被排序。
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
}

非递归版

思路

递归版本时,我们通过将要排序的序列分解、合并,在合并的过程中完成排序。在非递归的版本中,合并的思路和代码实现是一样,主要是如何将序列分解,递归版本可以利用子问题分治实现,非递归就要用循环模拟递归,我们这里引入一个gap
,代表序列的数据个数,首先让gap等于1,这样就将序列分解为好了,然后开始两两归并,之后让gap不断2倍化,直到gap等于原数组的数据个数。这里分解后的序列首位下标之差就是gap-1(因为是双闭区间,序列的数据个数就是gap)。这里还要注意分解的序列的首尾下标不能超过原序列的数据个数。
在这里插入图片描述

代码实现

void MergeSortnonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}//临时数组,存归并好的数据
	int gap = 1;//分解好的序列的数据个数为gap
	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;//要归并的2个序列的首尾下标
			int j = begin1;
			if (end1 >= n || begin2 >= n)
			{
				break;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}//保证首尾下标不越界
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}//排序并合并数据
			memcpy(a +i, tmp +i, sizeof(int) * (end2 - i + 1));//将归并好的数据拷贝给原数组
		}
		gap *= 2;//放大排序序列的区间,begin1到end1和begin2到end2这两个区间的数据个数是2倍的gap,所以gap *= 2后新序列还是有序的,只需继续将新序列两两归并即可。
	}
}

结果演示

int main()
{
	int a[] = { 2,5,9,1,6,11,3,4 };
	int n1 = sizeof(a) / sizeof(a[0]);
	MergeSort(a, n1);
	printf("MergeSort:");
	for (int i = 0; i < n1; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
	int b[] = { 2,7,3,4,1,2,6,5,11,8 };
	int n2 = sizeof(b) / sizeof(b[0]);
MergeSortnonR(b, n2);
printf("MergeSortnonR:");
	for (int i = 0; i < n2; i++)
	{
		printf("%d ", b[i]);
	}
	return 0;
}

在这里插入图片描述

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

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

相关文章

基于深度学习的时间序列算法总结

1.概述 深度学习方法是一种利用神经网络模型进行高级模式识别和自动特征提取的机器学习方法&#xff0c;近年来在时序预测领域取得了很好的成果。常用的深度学习模型包括循环神经网络&#xff08;RNN&#xff09;、长短时记忆网络&#xff08;LSTM&#xff09;、门控循环单元&a…

数据库知识汇总之MySQL

目录 MySQL数据库特点MySQL下载MySQL配置文件初始化MySQL配置安装MySQL服务 启动MySQL服务登录数据库修改数据库登录密码MySQL错误代码1130 MySQL数据库特点 MySQL是一个开源关系型数据库管理系统(RDBMS)&#xff0c;由Oracle公司维护和开发。它使用SQL语言进行数据库管理和操…

mfc140.dll丢失了要怎么解决?多种解决mfc140.dll方法对比

mfc140.dll丢失了怎么办&#xff1f;mfc140.dll丢失的多个解决方法今天就来给大家详细的说说&#xff0c;因为平时实在是太多人咨询这个问题了&#xff0c;都说自己电脑的mfc140.dll找不到了&#xff0c;一些程序没办法运行&#xff0c;所以还是给大家分析一下mfc140.dll。 一.…

droupout(Pytorch中的代码实现)

图片来源&#xff1a; 【Pytorch】torch.nn.Dropout()的两种用法&#xff1a;防止过拟合 & 数据增强-CSDN博客 注意&#xff1a; droupout可以进行数据增强或者防止数据过拟合。 droupout在全连接层之后&#xff0c;使得部分神经元失活&#xff0c;但是为什么能保持数据…

使用官方构建工具来创建一个vue3的项目

当你使用 Vite 构建项目时&#xff0c;可能会发现在命令行界面无法选择是否包含 TypeScript 等其他基础配置。此外&#xff0c;使用 vue create 命令创建项目时&#xff0c;默认会使用 vue-cli&#xff0c;但项目启动等过程可能较慢。在这种情况下&#xff0c;你可以参考以下步…

如何使用Java采集汽车之家车辆配置参数信息

目录 一、引言 二、采集工具选择 三、采集流程设计 1、确定采集目标 2、确定采集URL 3、发送HTTP请求 4、解析HTML页面 5、CSS选择器或jQuery选择器。 6、异常处理和日志记录 四、代码实现示例 五、结果与分析 六、结论 随着互联网的普及和信息技术的不断发展&…

VS代码生成工具ReSharper v2023.3正式发布——支持C# 12

实质上&#xff0c;ReSharper特征可用于C#&#xff0c;VB.net&#xff0c;XML&#xff0c;Asp.net&#xff0c;XAML&#xff0c;和构建脚本。 使用ReSharper&#xff0c;你可以进行深度代码分析&#xff0c;智能代码协助&#xff0c;实时错误代码高亮显示&#xff0c;解决方案范…

Redis基础系列-哨兵模式

Redis基础系列-哨兵模式 文章目录 Redis基础系列-哨兵模式1. 引言2. 什么是哨兵模式&#xff1f;3. 哨兵模式的配置4. 哨兵模式的启动和验证4.1 主master宕机&#xff0c;看会出现什么问题4.2 重启6379主机 5. 哨兵模式的工作原理和选举原理5.1. SDown主观下线&#xff08;Subj…

Linux 下GEO Server发布图层后,中文乱码解决方案

发布的图层&#xff0c;显示中文乱码&#xff0c;都是框框&#xff1a;如“口口” 第一步先查看Linux字符集 如下命令所示&#xff1a; 1.查看当前系统语言 echo $LANG2.查看安装的语言包 locale如果上面的命令执行后显示的是en_US.UTF-8&#xff0c;则说明当前语言系统及安…

【STM32】STM32学习笔记-MPU6050简介(32)

00. 目录 文章目录 00. 目录01. MPU6050简介02. MPU6050参数03. MPU6050硬件电路04. MPU6050框图05. MPU6050常用寄存器06. 附录 01. MPU6050简介 •MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0…

2024年甘肃省职业院校技能大赛信息安全管理与评估 样题一 模块二

竞赛需要完成三个阶段的任务&#xff0c;分别完成三个模块&#xff0c;总分共计 1000分。三个模块内容和分值分别是&#xff1a; 1.第一阶段&#xff1a;模块一 网络平台搭建与设备安全防护&#xff08;180 分钟&#xff0c;300 分&#xff09;。 2.第二阶段&#xff1a;模块二…

《动手学深度学习》学习笔记 第8章 循环神经网络

本系列为《动手学深度学习》学习笔记 书籍链接&#xff1a;动手学深度学习 笔记是从第四章开始&#xff0c;前面三章为基础知识&#xff0c;有需要的可以自己去看看 关于本系列笔记&#xff1a; 书里为了让读者更好的理解&#xff0c;有大篇幅的描述性的文字&#xff0c;内容很…

前端框架前置学习Node.js(2)

npm - 软件包管理器 定义 npm是Node.js标准的软件包管理器 npm仓库中包含大量软件包,使其成为世界上最大的单一语言代码仓,并且可以确定几乎可用于一切的软件包 最初是为了下载和管理Node.js包依赖的方式,但其现在已成为前端JavaScript中使用的工具 使用: 1.初始化清单文…

使用Dockerfile构建镜像的详细指南

目录 前言 一、什么是 Dockerfile 二、使用 Dockerfile 定制镜像 开始构建镜像 上下文路径 三、指令详解 四、构建阿里云仓库 前言 Docker是一种流行的容器化平台&#xff0c;可以帮助开发人员和运维团队更轻松地构建、发布和运行应用程序。在Docker中&#xff0c;镜像是…

WIFI7时代正式来临

Wi-Fi联盟在2024年1月8日宣布推出了Wi-Fi CERTIFIED 7认证&#xff0c;标志着WIFI7时代的正式来临&#xff01;这一认证引入了一系列强大的新功能&#xff0c;旨在提升Wi-Fi性能并改善各种连接环境。WIFI7支持多用户AR/VR/XR、沉浸式3D培训、电子游戏、混合工作、工业物联网和汽…

docker-compose安装HertzBeat赫兹跳动监控H3C交换机

前面我们用docker方式安装了HertzBeat&#xff0c;现在我们自己写个docker-compose.yml文件、创建文件直接docker-compose up -d直接启动运行 使用docker-compose需要先安装docker和docker-compose1、输入以下两段命令 mkdir 123 && cd 123 && mkdir data &a…

运筹说 第45期丨多目标规划发展及其提出者—— Abraham Charnes和William W. Cooper

经过前面的学习&#xff0c;相信大家已经对运筹学的运输问题有了更加全面的了解&#xff0c;接下来小编将带你学习新一章的内容&#xff0c; 先来看看多目标规划的发展简史&#xff0c;然后再带你领略该理论两位提出者的传奇一生&#xff01; 01目标规划发展简史 Vilfredo Pa…

JMeter笔记(三)

个人学习笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 目录 一&#xff1a;参数化方法 1&#xff09;用户定义的变量 2&#xff09;函数助手 3&#xff09;…

C++标准学习--智能指针

shared_ptr和weak_ptr的配合使用是个问题。unique_ptr的使用场合似乎比较局限。 文章C 智能指针详解&#xff08;一&#xff09;——unique_ptr - 知乎 (zhihu.com) 介绍了unique_ptr的使用。它可以由shared_ptr转来&#xff0c;主要用到了std::move。 主要场景其中提到&#…

POI-tl 知识整理:整理5 -> 开发一个插件

实现一个插件就是要告诉我们在模板的某个地方用某些数据做某些事情&#xff0c;我们可以通过实现RenderPolicy接口开发自己的插件 模板 1 写一个将标签替换为Hello, world的插件 import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.policy.RenderPolicy; import…