排序算法之归并排序

news2025/7/11 1:32:21

目录

       归并排序递归实现

思想

图解

代码

归并排序的非递归版本

基本思想:

代码


归并排序递归实现

 思想

最主要的相当于二叉树遍历中的后序遍历。

①将数组分割成多个小区间(当只有一个元素或者并不存在的时候就不用再分割了)

②对每一个小区间中的元素进行比较,从小到大排好之后,再返回给上一层;这一层排好之后再返回给这一层的上一层,直到排好整个区间内的元素。先分割左边的区间,再分割右边的区间,再对左区间进行排序,排好之后再排序右区间,最后合在一起。

需要借助一个额外的数组tmp,这一层递归的有序的结果是需要返回给上一层的。最后将排好序的tmp拷贝回a中

进行拷贝的条件是两个区间都存在,即有数据,如果不满足条件跳出循环,有可能其中一个还有数据没有拷贝完成,就要将剩下的数据全部都拷贝回数组

图解

  代码

void _MergeSort(int* a, int begin, int end, int* tmp)
{
	assert(a && tmp);
	while (begin >= end)
	{
		return;
	}//

	int mid = (begin + end) / 2;
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid + 1, end, tmp);//分

	int begin1 = begin;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = end;
	int i = begin1;

	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}

void MergeSort(int* a, int n)
{
	assert(a);
	int* tmp = (int*)malloc(sizeof(n));
	if (tmp == NULL)
	{
		printf("malloc fail!\n");
		exit(-1);
	}

	_MergeSort(a, 0, n - 1, tmp);

}

归并排序的非递归版本

基本思想:

递归排序的非递归版本由于是后序遍历,用栈和队列不太适合(比较适合前中序遍历)。

写成非递归版本主要是控制相应的区间的取值。我们可以手动进行控制,和刚才归并排序的思路差不多,相当于所有的都分成单个的区间,排好之后再返回给上一层排序,以此类推,知道排完

这里注意边界条件的控制

1 gap一开始的时候是1,这样子可以保证将数组分割成一个一个数字的小区间

2 循环的条件是gap<n,因为当gap等于n的时候是最后一层递归,相当于gap等于整个数组。

3 i+=2*gap的原因是一次归并的相当于两个数据,(大小区间都可以看做是一个数据。从宏观上来讲)

4 特别要注意边界条件的判断 如果只是单纯的这样写,不加边界条件的判断,那么很有可能会越界,只适合2^n的个数的数组

越界除了begin1都有可能越界

①如果end1和begin2越界了,那么就说明后面的一段区间是不存在的,我们可以不用判断这一个区间了(其他区间都是已经排好序的)

②如果是end2越界了,那么就需要修正end2的值,修正成数组的大小

注意这样子的话我们是需要每一次都将原数组的数据拷贝回a数组的,因为如果不判断就去递归的话,相当于这个数据不会返还给a了,那么对应的这里的位置就是随机值了。每递归一次返回一次是为了避免出现随机值

由于图和刚开始的差不多,就不画了

代码

void MergeSortNonR(int* a, int n)
{
	assert(a);
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc");
		exit(-1);
	}

	int gap = 1;
	while (gap < n)
	{
		int index = 0; 
		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 (end1 >= n || begin2 >= n)
			{
				break;
			}
		
			if (end2 >= n)
			{
				end2 = n - 1;
			}

			//归并
			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++];
			}


		}
		for (int j = 0; j < index; j++)
		{
			a[j] = tmp[j];
		}
		gap *= 2;
	}

	free(tmp);
	tmp = NULL;
}

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

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

相关文章

某工控图片上传服务 CPU 爆高分析

一&#xff1a;背景 1.讲故事 今天给大家带来一个入门级的 CPU 爆高案例&#xff0c;前段时间有位朋友找到我&#xff0c;说他的程序间歇性的 CPU 爆高&#xff0c;不知道是啥情况&#xff0c;让我帮忙看下&#xff0c;既然找到我&#xff0c;那就用 WinDbg 看一下。 二&…

Linux进程概念和控制(必备知识)

文章目录1、冯诺依曼体系结构2、操作系统3、进程<1>进程的创建<2>进程查看<3>进程状态<4>进程优先级<5> 进程地址空间4、环境变量5、进程控制<1>进程终止<2>进程等待<3>进程替换1、冯诺依曼体系结构 我们常见的计算机&#x…

软考 - 软件工程

软件过程基本概述 基本要素 方法工具过程 软件过程模型 能力成熟度模型CMM 能力成熟度模型CMMI 统一过程UP模型 针对大型项目 三大特别 用例和风险驱动以架构为中心迭代并且增量 四个阶段 起始&#xff1a;确认需求和风险评估精化&#xff1a;核心架构设计构建&#xff1a;构…

Linux内核开发 | Linux内核目录结构分析(5.4.32)

文章目录1. arch2. block3. certs4. crypto5. Documentation6. drivers7. fs8. include9. init10. ipc11. kernel12. lib13. mm14. net15. samples16. scripts17. security18. sound19. tools20. usr21. virt本文以Linux主线5.4.32内核版本进行分析。1. arch 该目录下包含了li…

【ROS】机械人开发--ROS工作空间与功能包

机械人开发--ROS工作空间与功能包一、ROS工作空间1.1 概念1.2 创建工作空间1.3 编译工作空间1.4 设置环境变量1.5 添加环境变量二、功能包2.1 概念2.2 功能包的内容2.3 创建功能包三、CMakeLists.txt文件四、package.xml文件一、ROS工作空间 1.1 概念 工作空间&#xff08;wo…

以“新IT”助“数智融合”,联想推开“智能化转型”下半场的大门

作者 | 曾响铃 文 | 响铃说 近年来&#xff0c;我国对数字化的重视达到前所未有的高度&#xff0c;从“十四五”规划纲要首次将数字经济单独列为一篇&#xff1b;到二十大报告中指出&#xff1a;“坚持把发展经济的着力点放在实体经济上”、“促进数字经济和实体经济深度融合…

SpringMVC学习篇(五)

SpringMVC之json数据传递 1.1 准备工作 1.1.1 导入lombok依赖(方便写实体类) <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency>1.1.2 导入mvc js…

mysql经典案例带解析(你没见过的全新版本)55题

首先给出初始表格 表格创建命令 create table emp(id int primary key auto_increment,name varchar(20),job varchar(20),manager int,hiredate date,sal double(8,2),comm double(6,2),dept_id int)charsetutf8;create table dept(id int primary key auto_increment,nam…

AcrelEMS-BP生物制药工厂能效管理系统

安科瑞 华楠 聚焦全厂能源采集、监控、分析、调度,降本提效,实现企业双碳目标;致力于全域化设备监视、巡检、故障报警、工单管理,运维优化,提升设备使用效率。 综合自动化系统 110kV及以下变电站综合自动化系统实现遥测、遥信、遥控、事故追忆、故障录波、安全防护、上传调度 …

搭建接口平台YApi详解(含搭建node环境)

公司之前使用的doclever 感觉不太好用&#xff0c;打算私有化部署YApi 步骤 准备使用yapi的可视化部署&#xff0c;需要有node环境 安装node环境 测试一下有没有node环境 如下就是有 [root192 sbin]# node -v v14.17.0 [root192 sbin]# npm -v 6.14.13没有就创建 cd /us…

webpack5 打包环境抽离分环境基本配置

两种开发模式 开发模式&#xff1a;代码能编译自动化运行生产模式&#xff1a;代码编译优化输出Webpack 基本功能 开发模式&#xff1a;可以编译 ES Module 语法生产模式&#xff1a;可以编译 ES Module 语法&#xff0c;压缩 js 代码Webpack 配置文件5 个核心概念 entryoutput…

FL Studio21最新演示测试版本下载FL水果V21

FL Studio是市场上最受欢迎的音乐制作软件之一。它被世界各地的许多专业制作人和艺术家使用。FL Studio音乐软件的每日下载量超过40&#xff0c;000次&#xff0c;其增长是不断的&#xff0c;而且没有迹象表明很快就会放缓。随着新的 FL 产品版本在 Windows 和 Mac 上不断发布&…

25.gateway的Filter 过滤器工厂(springcloud)

1 概述 gateway 里面的过滤器和 Servlet 里面的过滤器&#xff0c;功能差不多&#xff0c;路由过滤器可以用于修改进入Http 请求和返回 Http 响应2 分类 2.1 按生命周期分两种 pre 在业务逻辑之前 post 在业务逻辑之后2.2 按种类分也是两种 GatewayFilter 需要配置某个路由&…

阿里同步神器Canal原理+安装+快速使用

文章目录前言Canal简介MySQL主备复制原理canal 工作原理1、MySQL配置1.1 修改MySQL配置支持binloglog-binmysql-binbinlog-formatROW1.2 创建canal用户1.3 重启mysql服务1.4 基本的查看binlog命令2、下载安装canal2.1 解压canal2.2 配置与mysql信息2.3 启动canal3. 快速使用3.1…

【文件传输】实现下载

文章目录下载&#xff1a;下载的过程&#xff1a;单文件传输&#xff1a;多文件传输&#xff1a;下载&#xff1a; 如下图&#xff1a; 如果刚发完size&#xff0c;客户端不回复ok&#xff0c;直接发送数据&#xff0c;会出现粘包问题。如果想要确保客户端收到数据&#xff0…

流行的前端开源报表工具有哪些?适合在企业级应用的

前端开源报表工具有很多&#xff0c;但是如果是企业级应用真心不建议选用。比如非要选择开源的报表工具&#xff0c;你需要投入一个或多个程序员来做这个事情&#xff0c;他们还得先学习这个开源报表工具的界面、功能使用操作等等&#xff0c;尤其是很多开源工具的学习资料还是…

dpdk Vhost 库

1、 怎么实现vhost_dev的VhostOps的vhost_set_vring_kick和vhost_set_vring_call&#xff1b; vhost_net kernel方式的vhost_set_vring_kick和vhost_set_vring_call依赖于/dev/vhost_net的ioctl。 有两种实现方式&#xff1a; 1、guest是server&#xff0c;dpdk vhost user是…

Sourcetree的实际使用开发笔记

目录 前言 一、Sourcetree是什么 二、Sourcetree使用步骤 1.创建仓库 2.拉取和推送的使用 3.创建新的自己的分支 三、使用Sourcetree来进行不提交本地的代码&#xff0c;而获取最新的代码拉取 总结 前言 本章主要是记录一下Sourcetree的基本使用功能。 一、Sourcetree是…

Android:Binder思考笔记

基础知识 进程空间划分 一个进程空间分为用户空间与内核空间。用户空间与内核空间都是虚拟内存&#xff0c;映射到物理内存。所有进程的内核空间映射到同一块物理内存&#xff0c;是共享的二者区别&#xff1a; 进程间&#xff0c;用户空间的数据不可共享&#xff0c;即用户空…

线性与树型数据结构可视化模拟器

线性与树型数据结构可视化模拟器 题目2:线性与树型数据结构可视化模拟器 [问题描述] 数据结构课程是计算机类专业的核心课程之一&#xff0c;是计算机科学与技术必修的专业基础课程。数据结构研究的范围和计算机软件有着密切的联系。课程涉及到大量的概念、定义以及数据结构的…