C语言,谁都能看得懂的归并排序

喜欢看排序算法动态效果的,可以看看这个网站

https://visualgo.net/zh/sorting

里面很多算法的动画解释,可以看到算法的排序效果,而且还附带了伪代码的实现过程。

本来想录制几张动图放上来,但是因为图片较大,传不上来,公众号对动态图片有限制,喜欢的同学可以点击我上面的链接,自己去尝试一下。

我画了一个图片,用来表示归并排序的运算过程

排序的过程

先把需要排序的数据分成两份。

把两份的数据依次进行排序并组合在一起。

再把排序后的两组数据进行并入一起排序。

好了,写代码吧

我们先实现,「把两份的数据依次进行排序并组合在一起

下面是实现这个的算法过程

/** r[] : 需要排序的数组* s[] : 排序后保存数据的数组* left: 排序的起始位置* mid : 排序的中间位置* right:排序的最右边位置*/
int merge(int r[],int s[],int left,int mid,int right)
{int i,j,k;i=left;j=mid+1;k=left;for(;i <= mid && j<=right;){if(r[i]<=r[j])s[k] = r[i++];elses[k] = r[j++];k++;}for(;i<=mid;)s[k++]=r[i++];for(;j<=right;)s[k++]=r[j++];return 0;
}

如果我们对两个数进行排序

经过上面的那个函数排序后,我们会把[3,1]排序成[1,3]。

——

那,如果我们需要对4个数字进行排序呢?

我们需要先把4个数字分成2组

然后,我们需要依次对上面的两组数据进行排序,得到下面新的两组数据

然后,我们需要把已经排序的两个数组进行排序

s[] 是保存的排序结果,r[] 是需要排序的数组。

left,mid,right 是排序数组中的三个位置。

left = 0;

right = 3;

mid = ( left + right )/2 = 1;

进入函数体,我们需要三个变量来协助我们进行运算

i = left = 0;

j = mid +1 = 1 +1 = 2;

k = left = 0;

它们看起来是这样子的

把r[i] 和 r[j] 两个数进行比较,把小的那个数放到s[k] 里面,然后再移位

比较之后变成

然后再执行下面的代码

for(;i <= mid && j<=right;){if(r[i]<=r[j])s[k] = r[i++];elses[k] = r[j++];k++;
}

这时候 j = 4

这时候就退出了 for 循环

退出for 循环后 就开始执行下面的 for 循环

 for(;i<=mid;)s[k++]=r[i++];for(;j<=right;)s[k++]=r[j++];

这样后,会变成这样

这样就退出 merge 函数

经过上面的过程,我们需要应该有点悟性,我们需要使用递归来解决这些问题

可以看下面的文章了解啥是递归

C 语言,你真的懂递归了吗?

然后呢,我们就写了一个这样的递归函数,放心吧,在学习树的时候,也是需要这种递归操作的。

/** r[] : 需要排序的数组* s[] : 排序后保存数据的数组* left: 排序的起始位置* right:排序的最右边位置*/
int merge_sort(int r[],int s[],int left,int right)
{int mid;int t[20];if(left==right)s[left]=r[right];else{mid=(left+right)/2;merge_sort(r,t,left,mid);/*sort left~mid*/merge_sort(r,t,mid+1,right);/*sort mid+1~right*/merge(t,s,left,mid,right);/*merge sort left,mid,right*/}return 0;
}

这个函数就是递归函数,递归最后退出机制是 

left == right 

再然后,我们需要一个 main 函数

完整的代码实现如下

#include <stdio.h>
#include <stdlib.h>/** r[] : 需要排序的数组* s[] : 排序后保存数据的数组* left: 排序的起始位置* mid : 排序的中间位置* right:排序的最右边位置*/
int merge(int r[],int s[],int left,int mid,int right)
{int i,j,k;i=left;j=mid+1;k=left;for(;i <= mid && j<=right;){if(r[i]<=r[j])s[k] = r[i++];elses[k] = r[j++];k++;}for(;i<=mid;)s[k++]=r[i++];for(;j<=right;)s[k++]=r[j++];return 0;
}/** r[] : 需要排序的数组* s[] : 排序后保存数据的数组* left: 排序的起始位置* right:排序的最右边位置*/
int merge_sort(int r[],int s[],int left,int right)
{int mid;int t[20];if(left==right)s[left]=r[right];else{mid=(left+right)/2;merge_sort(r,t,left,mid);/*sort left~mid*/merge_sort(r,t,mid+1,right);/*sort mid+1~right*/merge(t,s,left,mid,right);/*merge sort left,mid,right*/}return 0;
}int main()
{int a[8] = {6,5,3,1,8,7,2,4};int i;merge_sort(a,a,0,7);for(i=0;i<sizeof(a)/sizeof(a[0]);i++)printf("%d ",a[i]);printf("\n");return 0;
}

程序输出

1 2 3 4 5 6 7 8

算法复杂度,翻开以前写的文章

时间复杂度和空间复杂度,一看就懂,面试前必过一遍

中间是 mid = (left+right)/2 

可以猜到是 O(logN) ,也就是排序的时间是用logN时间去拆分的,而且拆分的时候,我们还需要进行排序,也就是代码里面提到的,排序的时间是O(n),所以在拆分和排序中需要花费的时间是 O(NlogN)。

拆分需要花费 O(logN) ,那合并的时候自然也需要花费O(logN)

总的算法时间是

O(NlogN + logN)  = O(NlogN)


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

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

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

相关文章

内核链表list.h文件剖析

内核链表list.h文件剖析 一、内核链表的结构【双向循环链表】 内核链表的好主要体现为两点&#xff0c;1是可扩展性&#xff0c;2是封装。可以将内核链表复用到用户态编程中&#xff0c;以后在用户态下编程就不需要写一些关于链表的代码了&#xff0c;直接将内核中list.h中的代…

CAN总线很难吗?CAN总线看不懂是不可能的!

CAN&#xff08;Controller Area Network&#xff09;即控制器局域网&#xff0c;是一种能够实现分布式实时控制的串行通信网络。想到CAN就要想到德国的Bosch公司&#xff0c;因为CAN就是这个公司开发的&#xff08;和Intel&#xff09;CAN有很多优秀的特点&#xff0c;使得它能…

C语言必须写main函数?最简单的 Hello world 你其实一点都不懂!

我们在刚写程序的时候&#xff0c;第一个都是 hello world&#xff0c;而在这里&#xff0c;完整的代码就是&#xff1a;我们打眼一看&#xff0c;其实很简单&#xff0c;就是引入头文件&#xff0c;写一个主函数&#xff0c;然后输出一句话&#xff0c;但是当我们编译出来ELF的…

源码包安装

一、源码包和RPM包的区别 1、区别 安装之前的区别&#xff1a;概念上的区别 安装之后的区别&#xff1a;安装位置不同 2、RPM包安装位置 是安装在默认位置中 注&#xff1a;安装位置是写RPM包的作者决定的 注&#xff1a;RPM包支持指定安装位置&#xff0c;但是不建议指定位置安…

Linux下修改SSH登录端口

Linux下修改SSH登录端口LINUX 的默认SSH 端口是 22。为了防止别人暴力破解&#xff0c;建议修改SSH 访问端口&#xff1a;vim /etc/ssh/sshd_config 找到Port 22 这一行&#xff0c;这是是默认端口22&#xff0c;现在改成Port 1234这个数字自己定&#xff0c;但是不要超过65536…

五岁的时候,你在干什么?

文章写在2021.2.7号——想不到啊想不到&#xff0c;这么快你就五岁了。今天是楠哥的生日&#xff0c;在五年前的今天&#xff0c;小伙子在深圳宝安妇幼出生&#xff0c;刚出生的时候&#xff0c;样子很丑&#xff0c;第一次见面&#xff0c;我心情很紧张&#xff0c;不怎么敢靠…

TQ210——核心板和底板

TQ210——核心板和底板 1、TQ210简介【TQ210_COREB核心板 TQ210_BOARD_V4底板】 三星Cortex-A8 S5PV210芯片&#xff0c;运行最大频率1GHZ&#xff0c;处理器内部为64/32位总线结构&#xff0c;32/32KB一级缓存&#xff0c;512KB二级缓存。自带3D加速引擎&#xff08;SGX540&a…

“华为天才少年”自制百大Up奖杯,网友:技术难度不高侮辱性极强

来源&#xff1a;雷锋网B站硬核黑科技Up主、AI算法工程师稚晖君&#xff0c;停更了好一阵子后&#xff0c;这位自称野生钢铁侠的超硬核Up主终于又发布了新作品。之所以停更这么久&#xff0c;Up主解释说&#xff0c;不是因为在野外被捕了&#xff0c;纯粹是因为工作太忙了。熟悉…

终极教程,带具体实验现象,1个GPIO控制2个LED显示4种状态,欢迎讨论!

芯片之家前几天发了一篇文章&#xff0c;讨论1个GPIO控制2个LED显示4种状态&#xff0c;并没有带具体的实验现象&#xff0c;有点小遗憾&#xff1a;绝妙&#xff01;1个GPIO控制2个LED显示4种状态&#xff0c;什么&#xff1f;你不信&#xff1f;&#xff08;点击阅读&#xf…

《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #15 ramzswap

HACK #15 ramzswap 本节介绍将一部分内存作为交换设备使用的ramzswap。ramzswap是将一部分内存空间作为交换设备使用的基于RAM的块设备。对要换出&#xff08;swapout&#xff09;的页面进行压缩后&#xff0c;不是写入磁盘&#xff0c;而是写入内存。可以使用的内存仅为完成压…

TQ210——底板部分原理图

TQ210——底板部分原理图 1、主电源接口&#xff08;过压过流保护&#xff09; 2、串行接口 2路5线RS232电平的DB9接口&#xff0c;4路TTLT电平扩展接口 COM1和PC之间通信需使用直连串口线 COM2和PC通信需使用交叉串口线 接口UART2可接GPRS模块实现打电话发短信功能&#xff1b…

有趣的灵魂百里挑一,Linux同学你低下头干嘛,起来说下这个问题。

今天我们不讲源码&#xff0c;不说面试题&#xff0c;我们来说点轻松的&#xff0c;聊点好玩的&#xff0c;我们来看看linux下有哪些酷酷的&#xff0c;有意思的命令。0x00 sl - 呜呜&#xff0c;让开&#xff0c;小火车来啦0x01 cowsay - 一起来 say hello0x02 cmatrix - 超级…

nodejs在cmd提示不是内部或外部命令解决方法

今天用cmd安装个库,结果发现node不是内部命令,于是搜索了下解决方法,解决方法是&#xff1a; . 找到变量值中node的安装地址,比如C:develop\nodejs,如果不是这个地址改成现在新的安装的地址,然后保存,重新打开cmd,输入 node -v 查看版本号,就会发现一切正常啦!当然这只针对于安…

用mtrace定位内存泄漏

一. 缘起有的公众号读者&#xff0c;看完我上次写给大学生的查bug方法后&#xff0c;希望我多分享一些查bug的实践经验和具体步骤&#xff0c;比如如何查内存泄漏和core dump问题。所以&#xff0c;就打算写这篇文章。二. 内存泄漏简介内存泄漏&#xff0c;是一个谈虎色变的问题…

为什么每个人都应该尝试Ubuntu下篇 Why Everyone Should Try Ubuntu 分享

但是老实说&#xff0c;我认为 Ubuntu 拥有长期的生存能力重要于其短期的实用主义。最近几年来&#xff0c;对于改进 Linux 桌面方面&#xff0c;Ubuntu 做得比其他发行版本要多。这就是我已详细讨论的&#xff0c;其带来的实际好处&#xff0c;但它也有许多不明确的地方。感谢…

陪我长大的村,镇,学校和家乡

我们村在广西河池市金城江区九圩镇江潭村山岳屯上面的字可以省略&#xff0c;因为看起来确实麻烦。地图上是这样显示的。小说我们村的那座桥&#xff0c;那座老桥据说是我爷爷那一辈人建起来的&#xff0c;用的是实打实的大石头。我上小学那段那会&#xff0c;我们同龄的小孩都…

Linux硬盘分区

MBR分区主分区&#xff1a;14&#xff0c;一块硬盘最多4个主分区&#xff0c;对主机必须有&#xff0c;主分区可以格式化ntfs&#xff0c;存数据。扩展分区&#xff1a;14&#xff0c;一块硬盘最多一个扩展分区&#xff0c;可以没有扩展分区&#xff0c;可以划分成更小的单元&a…

使用FileZilla Server轻松搭建个人FTP服务器

使用FileZilla Server轻松搭建个人FTP服务器 添加一个用户&#xff0c;然后在“共享文件夹”下设置将要设为FTP目录的文件夹和操作权限&#xff0c;点击确定 https://jingyan.baidu.com/article/ed15cb1bb6de421be3698188.html 可以为不同的用户创建不同的目录&#xff0c;新建…

TQ210——启动方式

TQ210——启动方式

AngularJS:应用

ylbtech-AngularJS&#xff1a;应用1.返回顶部 1、AngularJS 应用 现在是时候创建一个真正的 AngularJS 单页 Web 应用&#xff08;single page web application&#xff0c;SPA&#xff09;了。 AngularJS 应用实例 您已经学习了足够多关于 AngularJS 的知识&#xff0c;现在可…