【排序】详细聊聊归并排序(含非递归)

news2025/2/5 22:11:14

目录

归并排序的基本思想:

递归算法:

递归算法的思路分析:

开辟数组的函数:

递归的函数:

非递归算法:

非递归的思路分析:

边界问题:

时间复杂度和空间复杂度分析:


归并排序的基本思想:

归并排序所采用的思想是将大问题分为小问题来处理,即我们常说的分治。

如图,要排序一个数组,我们就把这个数组往小的区间拆分,比如要排序数组,先排序左边数组,再排序右边数组,被分开的两个数组可以继续按照这种方式,继续分成更小的区间,直到每个区间只有一个数字的时候,再通过比较 相邻区间来插入到数组中,当然,这里插入的数组我们需要额外开辟。

归并排序的逻辑我们理清楚后,有两种方式来实现:递归和非递归,我们分别来介绍一下

递归算法:

递归算法的思路分析:

显然归并排序将大问题分治为小问题的思想是非常显然也是很适合用递归去解决的

写好递归逻辑的代码,由于我们需要开辟数组,因此我们将递归代码单独封装成另一个函数,在开辟数组的函数里调用就可以:

开辟数组的函数:

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

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

	free(tmp);
	tmp = NULL;
}

递归的函数:

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);

	//归并[begin,mid] [mid+1,end]
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
    //每个区间的i都是不同的,因此i要从begin开始
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
    //如果某个区间还剩下数据,直接插入到tmp的后面
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}

	memcpy(a+begin,tmp + begin,sizeof(int)*(end - begin + 1));
}

非递归算法:

非递归的思路分析:

归并排序的递归算法非常简单且容易理解,我们主要来看非递归算法:

非递归算法本质也是分治的思想,只不过在非递归算法这里,我们直接从一个一个的数据开始排序

第一次排序范围:0~0   1~1   2~2   3~3   4~4   5~5   6~6   7~7(每组一个)

第二次排序范围:0~1   2~3   3~4   4~5   5~6   6~7(每组两个)

第三次排序范围:0~3   4~7(每组四个)

int rangeN = 1;
	while (rangeN < n)
	{
		for (int i = 0;i<n;i+=2*rangeN)
		{
			int begin1 = i, end1 = i + rangeN - 1; 
			int begin2 = i + rangeN, end2 = i + 2 * rangeN - 1;

			int j = i;
			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,tmp,sizeof(int)*n);
		rangeN *= 2;
	}

边界问题:

弄清楚非递归是如何处理数据的,我们还需要考虑一个问题:边界问题

 上述四个变量中,有三种越界的情况:end1越界,begin2越界,end2越界

针对上述问题,我们要修改对应的边界,防止越界:

void MergeSortNONR(int* a,int n)
{
	int* tmp = (int*)malloc(sizeof(int)*n);
	if (tmp == NULL)
	{
		exit(-1);
	}
	int rangeN = 1;
	while (rangeN < n)
	{
		for (int i = 0;i<n;i+=2*rangeN)
		{
			int begin1 = i, end1 = i + rangeN - 1; 
			int begin2 = i + rangeN, end2 = i + 2 * rangeN - 1;

			int j = i;
			if (end1 >= n)
			{
				end1 = n - 1;
				begin2 = n;
				end2 = n - 1;
			}
			else if (begin2 >= n)
			{
				begin2 = n;
				end2 = n - 1;
			}
			else 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,tmp,sizeof(int)*n);

		rangeN *= 2;
	}
}

时间复杂度和空间复杂度分析:

时间复杂度:

归并排序的时间复杂度比较容易计算,由于是树的结构,时间复杂度是标准的O(nlogn)

空间复杂度:

由于归并排序需要开辟额外数组,所以空间复杂度是O(N),这也是归并排序的缺点


至此我们就讲解完成了递归方式和非递归方式实现归并排序,如果对你有所收获,还请点赞关注,我们下次再见

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

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

相关文章

重建农场2.0:实景三维数据中心一站式解决方案

面向实景三维中国建设&#xff0c;如何扩大产能&#xff0c;不断提升实景三维数据中心的重建算力水平&#xff1f;如何满足快速迭代的需求&#xff0c;不断提升数据中心的应变能力&#xff1f;如何做到“一机多能”&#xff0c;不断外延数据中心的硬件价值&#xff1f;在前不久…

jquery获取父/子iframe页面的URL

最近因为要演示,做个临时ifame框架页面,因此子页面要根据父页面url来指定跳转。下面为ifame页面: 1、获取子页面url: var currentpath = window.location.pathname; console.log(currentpath); 输出为:/JG/TJ_JILU.aspx 2、获取父页面url: let currentTopHref = wind…

IDEA 注释模版

类的主注释 /*** description TODO* author Gaoxueyong* date ${DATE} ${TIME}* version 1.0*/方法的注释 1、创建自己的分组 选择右侧Template Group并输入名称 2、创建自己的模版 选择自己创建的分组然后选择Live Template 然后在Template text框内写入 *** $description…

脑图谱的一致性问题

脑图谱的意义及一致性问题 我们如何定义大脑的解剖结构&#xff0c;并将这些结构与大脑的功能联系起来&#xff0c;可以限制或增强我们对行为和神经系统疾病的理解大量可用的脑图谱给研究健康群体和患病人群的可重复性和描述大脑不同区域参与各种疾病的荟萃分析带来了问题——…

全力推进企业数智赋能发展主线,低代码任重道远

信息化进程 纵观近半个世纪以来我国信息化的发展&#xff0c;经历了20世纪80年代以个人计算机普及应用为特征的数字化阶段&#xff08;信息化1.0&#xff09;&#xff1b;20世纪90年代中期以互联网大规模商用为特征的网络化阶段&#xff08;信息化2.0&#xff09;&#xff1b;…

毕业设计 基于java web的网上招标系统

文章目录前言一、项目设计1. 模块设计注册用户部分管理员部分2. 实现效果二、部分源码最后前言 今天学长向大家分享一个 毕业设计项目: 基于java web的网上招标系统 一、项目设计 1. 模块设计 注册用户部分 1&#xff1a;查看网站流程&#xff1a;查看与网站有关的流程信息…

ZBC成功上线PancakeSwap的糖浆池,并有望在不久上线Binance

近期流支付协议Zebec Protocol正在成为加密行业备受瞩目的Web3生态&#xff0c;其在此前与Visa合作推出可以使用加密货币进行支付的借记卡Zebec Card后&#xff0c;得到了Visa创始团队成员在技术、市场发展前景上的高度认可。与此同时&#xff0c;Zebec Protcocol也与尼泊尔财政…

【react-脚手架】

目录bug初始化脚手架react脚手架创建项目并启动脚手架文件介绍案例&#xff1a;hello react快捷键组件化编码流程脚手架配置代理方法前置说明常用的ajax请求库配置方法一&#xff1a;只能配置一个路径配置方法二&#xff1a;配置多个路径引入bootsrtrap消息订阅与发布&#xff…

YOLO系列目标检测算法——YOLOX

YOLO系列目标检测算法目录 - 文章链接 YOLO系列目标检测算法总结对比- 文章链接 YOLOv1- 文章链接 YOLOv2- 文章链接 YOLOv3- 文章链接 YOLOv4- 文章链接 Scaled-YOLOv4- 文章链接 YOLOv5- 文章链接 YOLOv6- 文章链接 YOLOv7- 文章链接 PP-YOLO- 文章链接 …

毕业设计 基于java web的企业财务管理系统设计与实现

文章目录前言一、项目设计1. 模块设计2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 java web 项目: 基于java web的企业财务管理系统设计与实现 适用于毕业设计、课程设计 一、项目设计 1. 模块设计 管理员的所有模块的功能分析&#xff1a; 部门信息管理…

2022年最火的8种编程语言~工作机会超多~

当今&#xff0c;我们已知的编程语言多达几百种&#xff0c;但是常被大家使用的只占少数&#xff0c;无论你是刚入行的新手还是一名成熟的开发者&#xff0c;了解编程语言的受欢迎程度都很有必要。 最近&#xff0c;国外网站DevJobsScanner公布了一项数据&#xff0c;他们在过…

[附源码]计算机毕业设计Node.js电子商城系统(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

用大约 10 万字的内容对 Java 的核心知识点和常见的 1000 多道面试题,做了详细的介绍

每个技术人都有个大厂梦&#xff0c;我觉得这很正常&#xff0c;并不是饭后的谈资而是每个技术人的追求。像阿里、腾讯、美团、字节跳动、京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司/小公司&#xff0c;如果说能够在这样的公司锻炼几年&#xff0c;相信对自己…

粗效过滤器安装技术参数

广州特耐苏净化设备有限公司详细介绍&#xff1a;粗效过滤器主要技术参数 粗效过滤器主要技术参数 粗效过滤器壳体材质&#xff1a;碳钢、不锈钢(304、304L、316、316L)、衬氟、塑料(PP、PVC等)。 粗效过滤器通常安装在泵、压缩机的入口或流量仪表前的管道上。 粗效过滤器安…

1978-2020年全国及31省市农业机械总动力(万千瓦)

1978-2020年全国及31省市农业机械总动力&#xff08;万千瓦&#xff09; 1、时间&#xff1a;1978-2020年 2、范围&#xff1a;31省 3、来源&#xff1a;各省NJ 农业统计NJ 4、缺失情况&#xff1a;无缺失 5、指标&#xff1a;农业机械总动力 6、指标解释&#xff1a; 农…

基于ssm jsp二手书交易系统源码和论文

随着信息技术的快速发展和网络技术的日益完善&#xff0c;人们越来越重视电子商务。校园 二手物品交易系统是校园电子商务的一个典型代表。二手市场从以前的路边旧货市场转 变到网络中&#xff0c;通过二手交易系统实现了二手交易。而校园二手物品交易系统带给学生省 时、省…

java调用groovy如何避免OOM

首先我们要清楚java执行groovy的逻辑&#xff0c;这里我们采用了GroovyClassLoader的方法&#xff0c;因为它能缓存编译结果&#xff0c;不用每次执行相同的脚本都需要重新编译&#xff0c;提升执行效率 GroovyCodeSource groovyCodeSource new GroovyCodeSource(context.get…

LeetCode HOT 100 —— 437. 路径总和 III

题目 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到子节点…

WebSocket新一代推送技术及Java Web实现

WebSocket简介 很多网站为了实现推送技术&#xff0c;所用的技术都是轮询。轮询是在特定的时间间隔&#xff08;如每1秒&#xff09;&#xff0c;由浏览器对服务器发出HTTP请求&#xff0c;然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点&#…

Visual Studio 控制台程序世界杯足球C语言版

Visual Studio 控制台程序世界杯足球C语言版程序之美前言主体运行效果核心代码逻辑分析结束语程序之美 前言 一年一度的世界杯如期而至&#xff0c;相信很多球迷小伙伴们一定不会错过这个难得的好机会&#xff0c;大饱眼福&#xff0c;美美的看上几场。 说起国际足联世界杯&a…