当前位置: 首页 > news >正文

归并排序有多简单?一幅图教你看懂【C语言】

目录

归并排序的递归实现 

代码实现

归并排序的非递归实现 

代码实现


归并排序的思想很简单——分治法。简单地说,归并排序的是将序列拆分成几段子序列,将每一段子序列分别进行排序,排好之后再将有序的子序列归并(有点像合并两个有序数组)成为一个有序的序列。

例如要排序数列:10、6、7、1、3、9、4、2;

将序列拆分为 2 个子序列;

继续拆分;

 

 继续拆分;

至此,每个子序列的长度都为 1 ,因为只有一个数,所以可认为是有序序列;

现将子序列两两归并,即合并两个有序序列;

继续归并;

继续归并; 

以上就是归并排序的整个过程,很显然归并排序的实现应该离不开递归的思想。

归并排序的递归实现 

归并排序的递归实现较为简单,需要注意的有两点:

1. 归并的过程并非在原数组上直接改动,而是开辟一个临时数组,在临时数组上进行排序,排好之后将临时数组的内容全部拷贝到原数组;

2. 代码中使用的是二路归并(如上图所示,每次将序列拆分为两个子序列)。

代码实现

void _MergeSort(int* a, int begin, int end, int* tmp)
{//递归的结束条件//当序列只有一个元素时或序列不存在时if (begin >= end)return;//将序列进行拆分 //[begin,mid]  [mid+1,end]int mid = (begin + end) / 2;//拆分的过程_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid+1, end, tmp);//以下为归并的过程int begin1 = begin, end1 = mid;int begin2 = mid+1, end2 = end;int i = begin;//归并:合并两个有序序列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)
{//开辟一个临时数组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;
}

归并排序的非递归实现 

非递归与递归作用思想基本相同。递归实现时,因为拆分序列时采用的是递归的方式,所以通过传递参数就可以控制子序列的长度。但是非递归不行,非递归通过变量 rangeN 来控制序列的长度(或间隔),每次让 rangeN *= 2 例如:

但是由于 rangeN 每次都 *2 ,而我们排序的序列长度不可能总是 2 的倍数,所以 可能会有数组越界访问的风险。例如:

现将两个子序列归并,并将数据拷贝回原数组时,就会发生越界:

当然这只是其中一种越界的可能情况——第二段序列发生越界,原因是右边界 end2 大于 n;

实际操作中,一共会有三种情况导致越界:

两段序列的区间分别为: [begin1,end1]  [begin2,end2]

1. end1 > n;

2. begin > n;

3.end2 > n;

所以,当这三种情况发生时,需要修正区间,以上述用例为例, end2 大于 n 时,令 end2 = n-1即可;

代码实现

void MergeSortNonR(int* a, int n)
{//开辟一个临时数组int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");exit(-1);}int rangeN = 1;while (rangeN < n){// i 控制访问子序列的位置for (int i = 0; i < n; i += 2 * rangeN){//拆分为两段子序列//[begin1,end1] [begin2,end2]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;}//释放与置空free(tmp);tmp = NULL;
}

相关文章:

归并排序有多简单?一幅图教你看懂【C语言】

目录 归并排序的递归实现 代码实现 归并排序的非递归实现 代码实现 归并排序的思想很简单——分治法。简单地说&#xff0c;归并排序的是将序列拆分成几段子序列&#xff0c;将每一段子序列分别进行排序&#xff0c;排好之后再将有序的子序列归并&#xff08;有点像合并两…...

C++-Z字扫描实现(Zigzag Scan)

Z字扫描(Zigzag Scan) 将二维矩阵压缩成行输出&#xff1a; int index0; for(int i0;i<rowscols-1;i){//i是第几条对角线if(i&1){//odd,向下扫描for(int jmax(0,i-cols1);j<min(i,row-1);j){res[index]mtx[j][i-j];}//}else{//偶数&#xff0c;向上扫描for(int jmi…...

【华为机试真题详解 Python实现】求最大数字【2023 Q1 | 100分】

文章目录 前言题目描述输入描述输出描述示例 1示例 2题目解析参考代码前言 《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即…...

面对数万亿产业规模,如何掘金工业互联网?

近年来&#xff0c;加速工业互联网建设的声音越来越响亮。一方面&#xff0c;政策利好&#xff0c;持续驱动。从2017年的《国务院关于深化“互联网先进制造业” 发展工业互联网的指导意见》到《工业互联网创新发展三年行动计划&#xff08;2021-2023年&#xff09;》&#xff0…...

#ifdefine #define #endif (避免头文件被重复包含的真正含义)

宏定义 首先在谈论正式话题之前&#xff0c;需要先介绍一个基础概念&#xff0c;也是前提&#xff0c;那就是宏定义。 #define demo 1 #define PI 3.14我们都知道这样会将demo 在预处理阶段替换或者说展开为1&#xff0c;Pi 替换为3.14。 #define 宏定义一个标识符来表示一个…...

单片机能运行操作系统吗?

先直接上答案&#xff1a;可以&#xff01;但是操作系统不是刚需&#xff0c;上操作系统比较占用单片机的资源&#xff0c;比如占用比较多的FLASH和RAM&#xff0c;间接增加了硬件成本&#xff0c;哪怕成本增加1毛钱&#xff0c;对于上量的产品&#xff0c;分分钟是一个工程师的…...

Python之webmagic爬虫优点与使用

一、webmagic的优点它更偏向于java的语法&#xff0c;对于熟悉java的工程师来说学习成本较低。提供多种选择器&#xff0c;如css选择器、xpath、正则等。有一个模块pipeline&#xff1a;可通过简单地配置&#xff0c;可以将爬虫抽取到的信息&#xff0c;持久化到文件、数据库等…...

代码随想录动态规划 || 121 122

Day42121. 买卖股票的最佳时机力扣题目链接给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返…...

C++STL库中不可或缺的部分—string(模拟实现)

前文大家好&#xff0c;本篇文章主要是讲解一下string一些常用接口的模拟实现。众所周知&#xff0c;在日常生活中&#xff0c;字符串无处不在&#xff0c;如just do it,中国,一坤年等&#xff0c;想要在计算机上将这些字符展现出来就需要用到string类&#xff0c;而对我们C程序…...

MySQL复合查询

文章目录基本查询回顾多表查询自连接子查询单行子查询多行子查询多列子查询在from子句中使用子查询合并查询unionunion all基本查询回顾 查询的员工部门表结构&#xff1a; mysql> show tables; ----------------- | Tables_in_scott | ----------------- | dept …...

PCIe 资料收集2

文章目录感官认识PCIe的存储空间PCIe 在 linux 下的驱动PCIe 验证1.PCIe 传递裸数据2.PCIe 转其他设备PCIe转其他总线RS232USB从用户空间理解PCIe感官认识 总线协议接口 视频介绍PCIe 视频介绍及PCIe文字介绍 PCIe上可以接各种控制器硬盘控制器硬盘声卡控制器音响咪头/耳机显…...

Linux网络编程(使用VScode远程登录ubuntu)

文章目录 前言一、SSH插件的安装1.SSH简单介绍2.SSH插件安装和配置步骤二、安装C/C++插件总结前言 本篇文章将带大家进行网络编程的准备工作,使用vscode进行远程登录ubuntu。为什么要使用vscode进行远程登录ubantu呢?因为有些小伙伴的电脑可能性能不够开启虚拟机后会导致电脑…...

如何提高项目估算精准度?关键看5大影响因子

如何让项目估算工作更加精准&#xff0c;我们需要重点关注5大调整因子。 1、功能点调整因子 首先需要对功能点因子进行调整&#xff0c;区分不同类型的系统特征值。 因为不同的系统&#xff0c;对项目开发的影响程度不同&#xff0c;一般我们把系统特征值分为14种类型&#xff…...

论文阅读笔记《Nctr: Neighborhood Consensus Transformer for Feature Matching》

核心思想 本文提出一种融合邻域一致性的Transfomer结构来实现特征点的匹配&#xff08;NCTR&#xff09;。整个的实现流程和思想与SuperGlue相似&#xff0c;改进点在于考虑到了邻域一致性。邻域一致性在许多的传统图像匹配和图匹配任务中都有应用&#xff0c;他基于一个很重要…...

上位机系统Ubuntu 20.04与下位机arduino UNO通讯

目录一、安装arduino IDE1.1安装方法1.1.1终端里命令下载&#xff08;不推荐&#xff09;1.1.2官网下载&#xff08;不推荐&#xff09;1.1.3论坛下载&#xff08;不推荐&#xff09;1.1.4系统应用商店&#xff08;推荐&#xff01;&#xff09;1.2配置项目文件位置1.3测试IDE功…...

hive面试题

1、什么是Hive Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查询功能&#xff08;HQL&#xff09; 2、Hive的意义&#xff08;最初研发的原因&#xff09; 避免了去写MapReduce&#xff0c;提供快速开发的…...

【CUDA】《CUDA编程:基础与实践》CUDA加速的关键因素

CUDA事件计时 CUDA提供了一种基于CUDA事件(CUDA event)的计时方式&#xff0c;可用来给一段CUDA代码(可能包含主机代码和设备代码)计时。 对计时器的封装&#xff1a; class CUDATimeCost { public:void start() {elapsed_time_ 0.0;// 初始化cudaEventcheckCudaRuntime(cud…...

数据结构【Golang实现】(四)——双向循环链表

目录0. 定义节点1. IsEmpty()2. Length()3. AddFromHead()4. AddFromTail()5. Insert()6. DeleteHead()7. DeleteTail()8. Remove()9. RemoveByValue()10. Contain()11. Traverse()0. 定义节点 type DLNode struct {Data anyPrev, Next *DLNode }// DoublyLoopLinkedLis…...

【Redis】高可用架构之哨兵模式 - Sentinel

Redis 高可用架构之哨兵模式 - Sentinel1. 前言2. Redis Sentinel 哨兵集群搭建2.1 一主两从2.2 三个哨兵3. Redis Sentinel 原理剖析3.1 什么哨兵模式3.2 哨兵机制的主要任务3.2.1 监控&#xff08;1&#xff09;每1s发送一次 PING 命令&#xff08;2&#xff09;PING 命令的回…...

图片的美白与美化

博主简介 博主是一名大二学生&#xff0c;主攻人工智能研究。感谢让我们在CSDN相遇&#xff0c;博主致力于在这里分享关于人工智能&#xff0c;c&#xff0c;Python&#xff0c;爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主&#xff0c;博主会继续更新的&#xff0c…...

面试官:关于CPU你了解多少?

CPU是如何执行程序的&#xff1f; 程序执行的基本过程 第一步&#xff0c;CPU 读取「程序计数器」的值&#xff0c;这个值是指令的内存地址&#xff0c;然后 CPU 的「控制单元」操作「地址总线」指定需要访问的内存地址&#xff0c;接着通知内存设备准备数据&#xff0c;数据准…...

UI自动化测试-Selenium的使用

文章目录 1. 环境搭建1.1 入门示例1.2 元素操作常用方法1.3 浏览器操作常用方法1.4 获取元素信息常用方法1.5 鼠标操作常用方法1.6 键盘操作常用方法1.7 下拉选择框操作2. 元素定位2.1 id定位2.2 name定位2.3 class_name定位2.4 tag_name定位2.5 link_text定位2.6 partail_link…...

嵌入式学习笔记——STM32的USART相关寄存器介绍及其配置

文章目录前言USART的相关寄存器介绍状态寄存器&#xff1a;USARTX->SR具体位代表的含义实际代码数据寄存器 USARTX->DR波特率寄存器 USARTX->BRR控制寄存器 (USART_CR)控制寄存器1&#xff08;USART_CR1&#xff09;控制寄存器2&#xff08;USART_CR2&#xff09;GPIO…...

Android setContentView流程分析(一)

对于做Android App的小伙伴来说setContentView这个方法再熟悉不过了&#xff0c;那么有多少小伙伴知道它的调用到底做了多少事情呢&#xff1f;下面就让我们来看看它背后的故事吧&#xff1f; setContentView()方法将分为两节来讲&#xff1a;   第一节&#xff1a;如何获取De…...

doris数据库操作数字遇到的问题

关于doris数据库Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库&#xff0c;以极速易用的特点被人们所熟知&#xff0c;仅需亚秒级响应时间即可返回海量数据下的查询结果&#xff0c;不仅可以支持高并发的点查询场景&#xff0c;也能支持高吞吐的复杂分析场景。…...

3.13文件的IO操作

一.文件1.定义文件一般指的是存储在硬盘上的普通文件形如:txt.jpg.mp4,rar等这些文件在计算机中,文件可能是一个广义的概念,不仅可以包含普通文件,还可以包含目录(也就是文件夹.把目录称为目录文件)在操作系统中,还会用文件来描述一些其他的硬件设备或者软件资源比如网卡,显示器…...

ffmpeg使用

1 下载FFmpeg安装 官网地址&#xff1a;https://www.ffmpeg.org/download.html#build-windows 进入网址&#xff0c;点击下面红框部分 点击下面范围进行下载&#xff0c;下载速度有点慢&#xff0c;等等吧&#xff01; 下载成功后&#xff0c;解压后&#xff0c;复制bin的路…...

spark中的并行度(分区数)/分区器如何确定

源头RDD有自己的分区计算逻辑&#xff0c;一般没有分区器,并行度是根据分区算法自动计算的&#xff0c;RDD的compute函数中记录了数据如何而来&#xff0c;如何分区的hadoopRDD&#xff0c;根据XxxinputFormat.getInputSplits()来决定&#xff0c;比如默认的TextInputFormat将文…...

00后女生“云摆摊”两周赚1.5万,实体店转战线上真的能赚钱吗?

最近&#xff0c;山东临沂的00后女生利用小程序在线上“云摆摊”卖水果&#xff0c;两周赚1.5万&#xff0c;引发网友热议。不少人发出质疑的声音&#xff1a;年轻人不要有稳定的工作不做&#xff0c;去摆摊&#xff1b;网上开店成本低&#xff0c;开实体店结果就难说了&#x…...

华为OD机试题 - 最优资源分配(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:最优资源分配题目输入输出描述备注示例一输入输出说明示例二输入…...

做公司网站建设价格/合肥关键词排名技巧

1, 数据 函数程序 都定义在 实例化对象中通过调用 实例化对象的函数方法 调用 实例化对象中 存储的数据执行程序 实现效果2, this指向必须是实例化对象匿名函数 --- 箭头函数回调函数 通过 bind() 语法修改设定 this指向提前定义一个变量 存储this指向一个函数中 要是用 多个…...

洛阳网站开发/seo关键词优化技术

xpath 省略中间路径在我的职业生涯的大部分时间里&#xff0c;我一直在从事软件开发工作&#xff0c;因此&#xff0c;即使我不止一次涉足解决方案工程&#xff0c;我还是把自己视为软件开发人员&#xff08;或软件架构师&#xff09;。 这肯定会对我如何看待架构景观产生影响&…...

沃尔玛超市/无线网络优化

前言LIUNX服务器部署&#xff0c;百度找的资料有些都是老的。查了一些资料顺便整合了一下&#xff0c;阿里云服务器(ECS)可以选择多种操作系统&#xff0c;打算用它运行Drupal或者WordPress&#xff0c;你最好选择Liunx系统&#xff0c;这篇文章的演示是基于阿里云的CentOS操作…...

做木业网站怎样起名/优秀软文营销案例

把网页的请求的js文件保存到本地并修改&#xff0c;使用fiddler拦截原来的请求&#xff0c;替换为本地的js文件...

网站制作厂家/网站的推广方法

1清楚一个项目的工作量有多少。 2了解一个项目中每一个组成部分的工作难度是怎么样的。 3对项目中每一个组成部分需要多少时间来完成心中要有数。 4熟悉同伴们的工作特点和强项所在&#xff0c;有针对性的分派任务。 5一定要分工明确&#xff0c;让每一个人清楚知道自己要完…...

wordpress posts_nav_link/湖南专业seo优化

我执行了一个impdp&#xff0c;但它没有完成&#xff0c;因为表空间中没有空间。我停止了impdb&#xff0c;现在我需要删除新建用户及其下的对象&#xff1a;SQL> drop user TEST cascade;drop user TGK_EXOR_IFIL_008_432 cascade*ERROR at line 1:ORA-00604: error occurr…...