经典排序算法详解

目录

创作不易,如对您有帮助,还望一键三连,谢谢!

前言

学习目标:

直接插入排序

基本思想:

代码

希尔排序:

gap取值

代码

特性总结

选择排序

基本思想

代码

堆排序

思想

代码

冒泡排序:

快速排序:

思想

递归

非递归

归并排序

基本思想:

递归实现

非递归实现

时间复杂度与空间复杂度以及稳定性


创作不易,如对您有帮助,还望一键三连,谢谢!

前言

排序在我们日常生活中十分常见,比如:成绩按高低排序,购物网页按价格排序......今天我们就来学习常见的几个排序算法。

学习目标:

接下来我们一个一个讲解。

直接插入排序

首先,我们先来看动图:

基本思想:

end从0开始,[0,end]视为一个有序的数组,然后每次都让end+1的数据与前面有序数组[0,end]进行对比排序,然后end++,直至遍历完整个数组,此时原数组就有序了。

代码

有小伙伴可能会问,为什么最后要pa[end+1]=tem ?且看此图:

这就是上面问题的原因,其实学习数据结构时,有这种问题究其原因还是因为没有画图,笔者认为学习数据结构一定要多画图,这样才不容易出错,有点跑题了哈哈,我们继续学习下一个排序。

希尔排序:

首先,希尔排序其实就是直接插入排序的变形,所以要理解希尔排序,我们得熟练掌握直接插入排序。我们先来看一下动图:

是不是看的一脸懵?这就对了,这个思路还是有点抽象的,容笔者慢慢讲解:

首先,我们要知道希尔排序其实就是直接插入排序的优化,它选取了一个值gap,并把数组分成gap个组,每个组两个元素相隔gap个位置,如下图所示:

至于gap如何取值,我们一会儿再讲,如上图,我们讲数组分成了gap组(5组),每组两两元素之间相隔gap个位置。

然后,我们对每一组进行直接插入排序,结果如下:

然后gap=gap/2,此时gap为2,在把数组分成gap(2)组,每组相邻元素相差gap位置,如下:

在对每组进行直接插入排序,排好后如下:

然后gap为1,将数组分成了1组,有10个元素,对改组进行直接插入排序:

自此,数组有序。

有小伙伴可能发现了,当gap为1时不就是直接插入排序吗?没错所以会说希尔排序就是插入排序的变形,实际上希尔排序就是插入排序的优化,希尔排序可比插入排序快多了。关于各排序的时间复杂度,我们下篇文章在讲解。

gap取值

gap取值的话

一般取法有多种,其中两种常见的是:

  1. 取 n/2

    • 最初的增量(gap)设定为数组长度的一半,即 gap = n / 2
    • 然后每次将 gap 减半,直到 gap = 1。
  2. 取 n/3+1

    • 初始增量(gap)设定为 gap = n / 3 + 1
    • 然后每次将 gap 按一定规则缩小,直到 gap = 1。

上面我们就是用了第一种方法。

当gap>1时,被称作为预排序;当ga1p=1为插入排序。

代码

代码如下:

果然,当我们了解思路后写代码,发现还是一样难写,哈哈哈。

第一个for循环,是控制所有组,确保每一组都能进行排序,一共有gap组,故为i<gap.

而这段代码,就是控制一组的排序,这个过程其实就是插入排序的变形,当gap=1时,与插入排序一模一样,我们可以画图来进行理解。

需要注意的是j<n-gap:

因为我们进行排序时,有pa[end+gap]=pa[end],所以我们要让j<n-gap,防止越界。

希尔排序还有另外一种写法:

这个写法与第一个不同的是没有按照先排好一个组,然后再排另一个组,它直接是混着排序,小伙伴们可以画图理解一下。两种方法掌握一种即可。

特性总结

选择排序

基本思想

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的 数据元素排完 。

这个排序思路还是比较简单的,

代码

好,我们给个样例运行一下:

不出意外,错了!

为啥呢?我们来调试一下:

第一轮,maxi为0,mini为9,没有错,我们在进行下面的交换代码。

出问题了,当我们把pa[begin]和pa[mini]进行交换时,由于maxi的值与begin相等,所以当交换pa[begin]和pa[mini]后,maxi指向的值就变了,不是最大值了,所以我们要加一个if条件语句:

这下就对了。

堆排序

思想

首先建堆,升序建大堆,降序建小堆,建好堆之后另end等于数组长度-1,交换0位置和end位置的数据,向下调整建堆end--,直至end小于0。

代码

这个堆排序写起来还是有难度的,这里看不懂也没关系,笔者之后专门写一篇堆排序的文章,可以暂时跳过继续往下看。

冒泡排序:

这个就比较简单了,冒泡排序没有什么实践价值,但有一定的教学意义,我们来看一下动图:

代码如下:

快速排序:

思想

我们找一个参考值,end指向数组尾部,begin指向数组起始位置。

end先走,如果arr[end]大于key,end--直至找到小于key的位置;

同理,当end找到小于key的位置后,begin开始找大于key的位置,然后交换begin和end两位置的值,直至begin=end。

当begin和end相遇时的位置的值一定小于key。(原因我们一会儿讲),然后交换key和两者相遇位置的值,完成第一趟排序。

快排是比较重要的,还是有很大的概率在面试时让你手撕,所以我们一定要熟练掌握,快排实现有递归和非递归两种方法,我们一一讲解。

递归

排完一次序后,以keyi为基准分割区间,继续排序.

代码如下:

非递归

有小伙伴可能会说:我们都已经会递归版本的快排了,还有必要学这个吗?往年一个面试官是这样问的:同学,你学过数据结构,那你了解快排吗?这位同学非常熟练的讲出来了递归实现的大致思路。面试官听后笑着说:“很好,那你能用非递归实现吗?”哈哈哈,所以还是有必要的。

非递归和递归思路一样,我们也是采用分割区间,不能用递归,我们可以用循环来解决,那么问题来了,我们怎么来存储分割好的区间呢?

想想我们之前讲过一道括号匹配的问题,那个时候我们怎么存储括号的?

答案是:栈。

我们用栈来存储分割后的区间,只要区间满足左边界大于右边界就入栈,然后套一个while循环,当战不为空就继续。

需要注意的是栈是后进先出,千万不要把区间搞反了

代码如下:

归并排序

基本思想:

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

说的通俗易懂点就是把一个数组分解成两个数组pa1,pa2,直到每个数组只有一个元素,然后在依次合并pa1和pa2,从而使原数组有序。

归并排序的思想很像我们之前讲过的合并两个有序数组,不知道小伙伴还记不记得,只能说是一模一样,同样,实现归并排序也有递归和非递归两种方式。

递归实现

需要讲的一点是_MergeSort是MergeSort的子函数,也可以稍作修改,写在一起.还有就是记得释放动态开辟的内存,养成良好的代码风格。

下面是递归大致展开图,可以帮助大家理解一下:

非递归实现

非递归实现,怎么实现呢?我们上面快排的非递归实现运用了栈来解决,那么这里能用栈来解决问题吗?可以,但是这里就比较麻烦,如果我们用栈来解决的话,那么循环的结束条件难以判断,同时此处栈管理起来也比较麻烦。我们这里可以用迭代来实现。

需要注意的是,我们每次要归并的两组数据,end1,begin2,end2有可能会越界,因为for循环的判断条件是i<n-1,此时除了begin1其余三个都可能会越界,所以我们要判断修正。

当begin2越界时,代表第二组越界,也就是不存在,所以不需要归并;当只有end2越界时,只需把end2修正为最后一个元素继续归并即可。其余也就没什么好说的了。

时间复杂度与空间复杂度以及稳定性

首先,我们先来了解一下稳定性的概念:

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次 序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法是稳定的;否则称为不稳定的。

如上图所示,即排完序后,黑6与红6的相对位置不变(黑6还在红6前面),那么这个排序就是稳定的。

知道了这个,我们接下来一个一个分析上面各个排序算法的时间复杂度、空间复杂度以及稳定性

1.直接插入排序

稳定性:稳定

时间复杂度:O(N^2);

空间复杂度:O(1)。

直接插入排序[0,end]有序,让arr[end+1]与[0,end]进行比较交换,当两数相等时,我们可以让其不交换,那么最后拍完序相等元素的相对顺序是不变的,所以说直接插入排序是稳定的。

通过上面的代码,不难分析出直接插入排序的时间复杂度为O(n^2),由于没开辟新的空间,所以说空间复杂度为O(1)。

2.希尔排序

稳定性:不稳定

时间复杂度:O(N*logN)

空间复杂度:O(1)

我们上面讲,希尔排序是插入排序的变形,那么希尔排序稳定吗?答案是不稳定

故希尔排序不稳定。那么希尔排序的时间复杂度又为多少呢?

这个就很复杂了,因为希尔排序循环次数与gap的取值有关,而gap又有很多种不同的取值方法,

同时,while循环比较次数和元素移动的次数也难以计算,所以说这需要很强的数学专业知识,笔者不会,但有大佬给出希尔排序的时间复杂度大概为O(N^1.3),记住就行。

那么希尔排序的空间复杂度为多少呢?很显然是O(1)。

3.选择排序

稳定性:不稳定。

时间复杂度:O(N^2);

空间复杂度:O(1)。

选择排序为什么不稳定的,这是个易错点,我们看下图的分析:

这种情况就是不稳定的情况。时间复杂度空间复杂度比较简单,不再赘述.

4.堆排序

稳定性:不稳定。

时间复杂度:O(n*logN)

空间复杂度:O(1)

由于堆我们之前没有讲解,讲起来有一点麻烦,我们先放一下,之后专门讲解堆的相关知识。

5.冒泡排序

稳定性:稳定

时间复杂度:O(N^2);

空间复杂度:O(1);

6.快速排序

稳定性:不稳定。

时间复杂度:O(N*logN);

空间复杂度:O(  logn)~O(n)。

快排也无法保证相等元素的相对位置,这个很好想例子,比如下图 :

这里的易错点就是空间复杂度不是O(1)!!!

函数递归需要额外开辟空间,我们上面也讲了,快排通常是递归实现的,N个数组成的数组每次被分成两个区间,依次分割,直到left>=right,它一共分了logN次,故需要开辟logN个新的空间

有小伙伴会问,递归递归,它往回归的时候,不是又应该开辟一块新空间吗?好问题,函数递归,回归时用的是已经开辟好了的空间。这涉及到函数栈帧的问题,有兴趣的小伙伴可以去学习学习,增强内力。

7.归并排序

稳定性:稳定

时间复杂度:O(N*logN).

空间复杂度:O(N).

也没什么好说的,比较简单。

总结图:

笔者希望大家能够理解性的去记忆这些东西,理解它们的原理,这样记忆起来就事半功倍了。

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

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

相关文章

【PHP项目实战训练】——后台-RBAC权限管理原理

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

Ubuntu多显示器设置不同缩放比例

Ubuntu多显示器设置不同缩放比例 设备问题解决方案 设备 笔记本屏幕分辨率为2560 \times 1600&#xff0c;外接显示器的分辨率为3840 \times 2160。 问题 Ubuntu默认的显示器设置中&#xff0c;缩放仅能选择100%&#xff0c;200%&#xff0c;300%&#xff0c;400%。假…

北邮《计算机网络》蒋老师思考题及答案-传输层

蒋yj老师yyds&#xff01; 答案自制&#xff0c;仅供参考&#xff0c;欢迎质疑讨论 问题一览 传输层思考题P2P和E2E的区别使用socket的c/s模式通信&#xff0c;流控如何反映到编程模型三次握手解决什么问题举一个两次握手失败的例子为什么链路层是两次握手而非三次&#xff1f;…

求生之路史低入手 教你怎么使用求生之路创意工坊提高体验性

求生之路是一款抵御丧尸的第一人称射击游戏&#xff0c;四名幸存者联机配合&#xff0c;在现代的城市中&#xff0c;击败各种丧尸还有强大的变种人BOSS&#xff0c;虽然是十几年前的游戏&#xff0c;但是毫不夸张的说&#xff0c;游戏丝毫不过时&#xff0c;目前steam夏促&…

数据结构5---矩阵和广义表

一、矩阵的压缩存储 特殊矩阵:矩阵中很多值相同的元素并且它们的分布有一定的规律。 稀疏矩阵:矩阵中有很多零元素。压缩存储的基本思想是: (1)为多个值相同的元素只分配一个存储空间; (2)对零元素不分配存储空间。 1、特殊矩阵的压缩存储 &#xff08;1&#xff09;对称矩…

数据库自动备份到gitee上,实现数据自动化备份

本人有个不太好的习惯&#xff0c;每次项目的数据库都是在线上创建&#xff0c;Navicat 连接线上数据库进行处理&#xff0c;最近有一个项目需要二次升级&#xff0c;发现老项目部署的服务器到期了&#xff0c;完蛋&#xff0c;数据库咩了&#xff01;&#xff01;&#xff01;…

从 Hadoop 迁移,无需淘汰和替换

我们仍然惊讶于有如此多的客户来找我们&#xff0c;希望从HDFS迁移到现代对象存储&#xff0c;如MinIO。我们现在以为每个人都已经完成了过渡&#xff0c;但每周&#xff0c;我们都会与一个决定进行过渡的主要、高技术性组织交谈。 很多时候&#xff0c;在这些讨论中&#xff…

游戏AI的创造思路-技术基础-深度学习(5)

继续深度学习技术的探讨&#xff0c;填坑不断&#xff0c;头秃不断~~~~~ 目录 3.5. 自编码器&#xff08;AE&#xff09; 3.5.1. 定义 3.5.2. 形成过程 3.5.3. 运行原理 3.5.3.1.运行原理及基本框架 3.5.3.2. 示例代码 3.5.4. 优缺点 3.5.5. 存在的问题和解决方法 3.5…

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(三)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

鸿蒙开发 之 健康App案例

1.项目介绍 该项目是记录用户日常饮食情况&#xff0c;以及针对不同食物摄入营养不同会有对应的营养摄入情况和日常运动消耗情况&#xff0c;用户可以自己添加食品以及对应的热量。 1.1登陆页 1.2饮食统计页 1.3 食物列表页 2.登陆页 2.1自定义弹框 import preferences from oh…

使用自定义的shiro密码匹配器CredentialsMatcher完成密码验证

今天突然想研究一下shiro怎么匹配用户的密码。 我们使用shiro的API登录时&#xff0c;会先创建一个令牌对象&#xff0c;而经常用的令牌对象是UsernamePasswordToken&#xff0c;把用户输入的用户名和密码作为参数构建一个UsernamePasswordToken&#xff0c;然后通过Subject.l…

十二、Yocto集成ROS2 app程序(package)

文章目录 Yocto集成ROS2 app程序1. 添加一个ros2 package应用程序2. 添加bb文件集成app应用程序 Yocto集成ROS2 app程序 本篇文章为基于raspberrypi 4B单板的yocto实战系列的第十二篇文章&#xff1a; 一、yocto 编译raspberrypi 4B并启动 二、yocto 集成ros2(基于raspberrypi…

stable diffusion 模型和lora融合

炜哥的AI学习笔记——SuperMerger插件学习 - 哔哩哔哩接下来学习的插件名字叫做 SuperMerger,它的作用正如其名,可以融合大模型或者 LoRA,一般来说会结合之前的插件 LoRA Block Weight 使用,在调整完成 LoRA 模型的权重后使用改插件进行重新打包。除了 LoRA ,Checkpoint 也…

Kafka入门到精通(三)-Kafka

Kafka简介 Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。 这种动作&#xff08;网页浏览&#xff0c;搜索和其他用户的行动&#xf…

pgsql的套接字文件不存在

问题&#xff1a;psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: No such file or directory 解决方式&#xff1a; 检查 postgresql.conf 文件中的 unix_socket_directories 设置&#xff0c;确保它包含 /tmp 或者你期望的目录。 重…

文本分析|小白教程

在信息爆炸的时代&#xff0c;文本数据无处不在&#xff0c;如何从这些海量的文字中提炼出有价值的信息呢&#xff1f;答案就是——文本分析。文本分析&#xff0c;简单来说&#xff0c;就是对文本数据进行深度的研究和分析。它能够从看似普通的文字中&#xff0c;提取出主题、…

sheng的学习笔记-AI-高斯混合模型(GMM)

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 需要学习前置知识&#xff1a; 聚类&#xff0c;可参考 sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 EM算法&#xff0c;可参考 sheng的学习笔记-AI-EM算法-CSDN博客 贝叶斯&#xff0c;可参考 sheng的学习笔记-AI-…

关于使用绿联 USB-A转RJ45 2.5G网卡提速的解决问题

问题 网络下载速率低 网线是七类网线&#xff0c;外接的USB网卡驱动 我的自带网卡是 I219v 在嵌入了2.5G网络后一直无法到达1.5G以上。 平均测速300~500M 解决方案 更新了USB的网卡驱动 禁用了 I219-V的驱动。测速即可 USB驱动下载地址 https://download.csdn.net/downlo…

分销裂变实战:PLG模式如何助力企业突破增长瓶颈

在竞争激烈的商业环境中&#xff0c;企业如何快速、有效地实现增长&#xff0c;一直是业界关注的焦点。近年来&#xff0c;分销裂变作为一种新兴的商业模式&#xff0c;凭借其独特的优势&#xff0c;逐渐受到企业的青睐。而产品驱动增长&#xff08;PLG&#xff09;模式更是为分…

JAVA:Word2Vec的使用

1、简介 Word2Vec是 Google 在 2013 年年中开源的一款将词表征为实数值向量的高效工具, 其利用深度学习的思想&#xff0c;可以通过训练&#xff0c;把对文本内容的处理简化为 K 维向量空间中的向量运算&#xff0c;而向量空间上的相似度可以用来表示文本语义上的相似度。 Wo…