排序(4)——归并排序

news2024/12/30 4:03:47

目录

前言

1.归并排序的递归实现

1.1 归并排序概念

1.2 归并排序递归实现

2.归并排序的非递归实现


前言

今天给大家带来比较排序的最后一种,归并排序,这个排序,需要我们对递归,循环控制要有着较强的理解,我相信大家通过前面和小编的一起学习,这里肯定也是得心应手。


1.归并排序的递归实现

1.1 归并排序概念

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

1.2 归并排序递归实现

这里我们看具体过程:

这里有个细节我们需要注意一下,在我们对数组进行排序的时候我们需要利用另外一个数组,然后在复制回原数组。

 这里我们的具体代码如下:

void _MergeSort(int* a, int*temp,int begin, int end)
{
	if (begin >= end)
	{
		return;
	}
	int mid = (begin + end) / 2;
	_MergeSort(a, temp, begin, mid);
	_MergeSort(a, temp, mid + 1, end);
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] >=a[begin2])
		{
			temp[i++] = a[begin2];
			begin2++;
		}
		else
		{
			temp[i++] = a[begin1];
			begin1++;
		}
	}
	while (begin1 <= end1)
	{
		temp[i++] = a[begin1];
		begin1++;
	}
	while (begin2 <= end2)
	{
		temp[i++] = a[begin2];
		begin2++;
	}
	memcpy(a + begin, temp + begin, sizeof(int)*(end - begin + 1));
}

//归并排序
void MergeSort(int* a,int n)
{
	int* temp = (int*)malloc(sizeof(int) * n);
	if (temp == NULL)
	{
		perror("malloc fail");
		return;
	}
	_MergeSort(a, temp, 0, n - 1);
	free(temp);
	temp = NULL;
}

这里由于我们需要使用到另外的数组去进行存储排序,但是由于局部变量在每次函数调用结束后会自动销毁,所以这里我们需要把数组建立在堆区,但是我们创建数组的操作是不能进行递归的,如果递归就会不断出现重复的数组,因此我们这里只需要把排序和复制回元组的操作进行递归,因此这里我们封装函数MergeSort以及函数_MergeSort.

由于这里我们是将数组元素不断分解直到剩一个元素,或者没有元素,然后先进行左右分解区间的排序,最后返回上一级,直到所有的元素都排序完毕,我们就直接结束排序。

这里我给大家详细讲解一下代码:

 

2.归并排序的非递归实现

对于非递归实现,之前小编给大家讲解了快速排序的非递归实现,但是相对于今天的归并排序,前者和树的前序遍历类似,后者和树的后序遍历类似,对于此类的递归我们,一般是从最小空间到最大空间不断控制,但是这个过程中有很多的细节需要我们自己掌握一下。

这里小编给大家演示一下具体过程:

 这里我们发现gap=gap*2,只有当我们的数组长度等于2的倍数的时候我们才能刚好分组,否则就会出现某些问题,例如:

那么对于这里的越界我们一共可能会出现三种越界情况,我们要对其分别进行控制

具体情况如下:

1.end1越界了,不归并

2.end1没有越界,begin2越界了,也不归并

3.end1没有越界,begin也没越界。end2越界了,我们需要修正end2

这里我们该怎么理解呢?首先我们需要知道一点,我们的分组是在小组已经排好序的情况下分的,所以我们要明白,begin1~end1这段区间是有序的,begin2~end2这段区间是有序的,但是begin1~end2这段不一定有序(如果都存在的话),那么对于情况一,如果end1越界说明这两段区间都不存在,所以我们就不需要将其归并,对于情况二,如果begin2越界了,但是end1没越界,由于begin1~end1,已经有序,所以我们也就不需要归并,对于情况三,如果只是begin2~end2部分越界,那么我们只需要将begin1~end1和begin2到数组末尾出现的元素进行归并即可。

那么我们的代码如下:

void MergeSortNonR2(int* a, int n)
{
	int* temp = (int*)malloc(sizeof(int) * n);
	if (temp == NULL)
	{
		perror("malloc fail");
		return;
	}
	int gap = 1;
	int i = 0;
	while (gap < n)
	{
		int j = 0;
		for (i = 0; i < n; i = i + 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + gap * 2 - 1;
			if (end1 >n-1&&begin2 > n - 1)
			{
				break;
			}
			else if(end2>n-1)
			{
				end2 = n - 1;
			}
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] <= a[begin2])
				{
					temp[j++] = a[begin1++];
				}
				else
				{
					temp[j++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				temp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				temp[j++] = a[begin2++];
			}
			memcpy(a+i, temp+i, sizeof(int)*(end2-i+1));
		}
		gap = gap * 2;
	}

}

 代码详解如下:

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

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

相关文章

【iOS的NSNULL nil Nil 】

前言 偶然看到了NSNULL 简单了解他的兄弟nil Nil记录一下。 NSNULL Nil nil 在iOS中&#xff0c;nil、Nil和NSNull都表示“空值”的概念&#xff0c;但它们在使用时有所不同。 nil和Nil都表示空指针&#xff0c;可以用于指针类型的变量、对象类型的变量、和Objective-C对象…

浙江海發進出口股份有限公司官网上线|LTD五金技术行业案例分享

​浙江海發進出口股份有限公司 (以下简称海發)是一家多元化的国际贸易企业。拥有自己的工厂&#xff0c;稳定的资金储备和最好的服务&#xff0c;在商业领域赢得了很高的声誉。地处长江三角洲交通经济中心嘉兴市。 浙江海發進出口股份有限公司 (以下简称海發)是一家多元化的国…

Python轻量级Web框架Flask(5)——Flask模型基础和数据迁移

0、前言&#xff1a;学习这部分的前提是对python的面向对象有一定的了解&#xff0c;同时对MySQL有扎实的学习 1、Flask模型基础知识&#xff1a; Flask模型 ORM &#xff08;注意&#xff1a;在flask中用ORM可以实现SQL语句功能&#xff0c;但是并不意味着SQL语句不重要&am…

NISACTF2023 WP

NISACTF2023 WP 前言 2年多没玩CTF了&#xff0c;pwn显得手生了不少&#xff0c;我的PWN环境已经在硬盘的某个角落里吃灰了。今天参加了一场校赛&#xff0c;捣鼓了一下午&#xff0c;Reverse和PWN都AK了。其实比赛是新手向&#xff0c;没啥难度&#xff0c;不过有道PWN设计的…

ChatGPT实战100例 - (02) 自动出PPT它不香么?

文章目录ChatGPT实战100例 - (02) 自动出PPT它不香么&#xff1f;一、需求与思路1. 需求&#xff1a;出个PPT&#xff0c;5分钟后要用2. 思路&#xff1a;生成markdown然后转化二、生成markdown语法的思维导图1. 问题2. 回答三、把markdown文本转换成PPTChatGPT实战100例 - (02…

STM32 gpio外部中断详解

什么是中断&#xff1f; 打断CPU执行正常的程序&#xff0c;转而处理紧急程序&#xff0c;然后返回原暂停的程序继续运行&#xff0c;就叫中断 中断的作用和意义 中断的意义&#xff1a;高效处理紧急程序&#xff0c;不会一直占用CPU资源 STM32 GPIO外部中断简图 NVIC 什么…

JSTL标签库

英文全称&#xff1a;Java Standard Tag Lib&#xff08;Java标准的标签库&#xff09; 使用目的&#xff1a;JSTL标签库通常结合EL表达式一起使用。目的是让JSP中的java代码消失。 使用位置&#xff1a;JSTL标签是写在JSP当中的&#xff0c;但实际上最终还是要执行对应的jav…

Ubuntu 开机启动 通过crontab定时器去检查脚本 实现

有个项目的程序需要实现开机启动 通过添加一个qmcy.service服务的方法 发现 确实执行脚本了 但是脚本的程序缺并没有起来 但是如果手动执行这个脚本 程序是能起来的 不知道为啥 没办法 网上搜了下 可以通过 crontab定时器去检查 程序是否启动 没启动的话去 执行对应的脚…

【毕业设计】基于程序化生成和音频检测的生态仿真与3D内容生成系统----程序化生成多图层地形贴图的算法设计

(2条消息) 【开发日志】2023.04 ZENO----Image Processing----CompositeCV、Composite2、Composite3_EndlessDaydream的博客-CSDN博客 (2条消息) 【开发日志】2023.04 ZENO----Image Processing----ImageEdit、EditRGB、EditHSV_EndlessDaydream的博客-CSDN博客 (2条消息) 【…

telegraf在iiot领域的基本应用(Modbus,OPC)

熟悉telegraf是因为influxdb缘故&#xff0c;当时telegraf主要是作为granfa监控的agent一环&#xff0c;很多文章有相关的介绍&#xff0c;但作为java开发对telegraf&#xff08;go语言开发&#xff09;也仅仅只是适用级别&#xff0c;这边文章也只讲到一些简单的应用。希望能帮…

<STM32>STM32CubeMX-CAN通信(扫描读取数据方式)(5)

&#xff1c;STM32&#xff1e;STM32CubeMX-CAN通信&#xff08;扫描读取数据方式&#xff09;&#xff08;5&#xff09; 本节主要讲解CAN通信的功能&#xff0c;主要采用扫面检测接收数据的方式&#xff1b; CAN的详细解说可参考《STM32F4XXX中文参考手册》&#xff0c;资料有…

CDH 之 Kerberos 安全认证和 Sentry 权限控制管理(一)

一、Kerberos 和 Sentry 概述 1.1 什么是 Kerberos Kerberos是一种计算机网络授权协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。这个词又指麻省理工学院为这个协议开发的一套计算机软件。软件设计上采用客户端/服务器结构&#xff0c;…

java微服务商城高并发秒杀项目--011.授权规则和系统规则

授权规则在shop-order-server中新建RequestOriginParserDefinition.java,定义请求来源如何获取Component public class RequestOriginParserDefinition implements RequestOriginParser {Overridepublic String parseOrigin(HttpServletRequest request) {/*** 定义从请求的什么…

文本分类论文阅读

1.ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information&#xff08;ACL2021&#xff09; 字形嵌入根据汉字的不同字体获得&#xff0c;能够从视觉特征中捕捉汉字语义&#xff0c;拼音嵌入表征汉字的发音&#xff0c;解决了汉语中非常普遍的异义异义现…

四、vue基础-指令(一)、vscode代码片段

一、vscode代码片段 我们在前面联系Vue的过程中&#xff0c;有些代码片段是需要经常写的&#xff0c;我们再VSCode中我们可以生成一个代码片段&#xff0c;方便我们快速生成。VSCode中的代码片段有固定的格式&#xff0c;所以我们一般会借助于一个在线工具来完成。 具体步骤如…

01_什么是Uboot

目录 U-Boot简介 获取Uboot U-Boot初次编译 U-Boot烧写与启动 U-Boot简介 Linux系统要启动就必须需要一个bootloader程序(裸机程序),也就说芯片上电以后先运行一段bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux镜像从flash(NAND,NOR FLASH,SD,EMMC等…

【防止恶意用户注册】-- 手机在网状态 API 的防欺诈应用解析

简介 手机在网状态 API 支持传入手机号码&#xff0c;查询手机号在网状态&#xff0c;返回在网、在网不可用、不在网&#xff08;销号/未启用/停机&#xff09;等多种状态&#xff0c;查询手机号在网状态之后&#xff0c;可以根据具体的业务需求来进行不同的处理。 本文主要介…

EA的使用---文档的生成

EA中文档的自动生成 1.找到如下界面 2.选择第一个 3.设置存储的位置 4.点击Generate 5.查看生成的文档

ViT Vision Transformer进行猫狗分类

文章目录依赖准备数据集合残差结构PatchEmbed模块Attention模块MLPBlockVisionTransformer结构模型定义定义一个模型训练VISION TRANSFORMER简称ViT&#xff0c;是2020年提出的一种先进的视觉注意力模型&#xff0c;利用transformer及自注意力机制&#xff0c;通过一个标准图像…

【C++STL精讲】string的模拟实现

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;定义string类&#x1f337;构造函数&#x1f337;拷贝构造函数&#x1f337;赋值重载&#x1f337;析构函数&#x1f337;[]操作符重载&#x1f337;比较运算符重载&#x1f337;c_str、size、capacity&#x…