排序进阶----插入排序,希尔排序

       各位看官们好,接下来鄙人想与大家分享的实现被称为六大排序之一的插入排序。其实关于这六大排序在我们最开始就已经接触过了。我们在最开始学习c语言的时候,我们要学习到其中之一的冒泡排序。虽然现在看起来冒泡排序确实是没有太大的实际效果,但是对于我们入门却还是有很大的帮助的。而我们下来介绍的插入排序这是比排序好很多的一个优质排序方法。那废话少说,们来看看插入排排序是如何实现的,并且在实现插入排序后,再看看比插入排序额还厉害的希尔排序

6c0ce7e7f5d14bab9539ea8a07f94f99.jpeg

插入排序思路 

        对于插入排序的话其实还算是比较好理解的。我想大家应该都玩过扑克牌吧。斗地主大家都知道,我们平常的习惯都是按大小排序。这个其实就是插入排序。大家可以想一下,我们如果以扑克牌为例,我们利用冒泡排序的话,每一个位置就要对比一下,这很麻烦,很耗时间的。但是如果我用插入排序的话,我们以第一个数为例,一次向后对比,如果他比接下来对比的数都大的话,那么我就先把战船一直比较比他更大的数,那么我就把它插入在前面。意思就是相当我们暂时把整个数组看着是有序的。那这个数一直对比,一直到遇到比他大的我在插入。在没遇见之前,我就一直想把它存起来。如果都他是最大的话,那么遇到最后一个循环,那么就结束。

      我想我这么说可能是比较难以理解的,大家可以看一下下面这张动图来理解一下。

afae4b37f7034ff18b12ca93ac553ca4.gif

         这样大家可能会理解起来比较简单一些。而且如果大家对数据机构有一点了解的话,就知道插入排序的时间复杂度最坏也才 O(n^2)。那么接下来我们就来尝试一下如何把插入排序写出来。

插入排序实现

         那么我们想想如何实现插入排序呢?我们先从第一趟开始,比如说我们就先走第一趟,以下标为零开始的与下标为一对比,如果他比第一个大的话,那么这一趟就结束,我们就只循环一次。下一次循环我们就循环两次,以下交换后的下标再次循环。如果比前面的数小的话,那么就结束循环。

void InsertSort(int* arr, int n)
{int end = 0;//待插入的元素int tem = arr[end + 1];//单趟排while (end >= 0){//比插入的数大就向后移if (tem < arr[end]){arr[end + 1] = arr[end];end--;}//比插入的数小,跳出循环else{break;}}arr[end + 1] = tem;
}

        这就是插入排序的单次排序。那么我们肯定不是循环一次就能将整个数组变为有序的。那么我就要多循环几次。我们可以看到我们代码最开始是以end开始的。我们把and设为0,那么它就是下标为0与下标为一对比,如果不能将它设为1,那么它就是与下面为1和下面为2对比。那我们就可以再写一个循环,将单次循环放进这个循环里面,End随循环次数增加,但是总体次数要小于我们传入的n小于1。因为我们自己设的要对比的下一个数就是end加一。如果我们这样最开始就是因为小于的话,那么会突出一个随机值。那么这样我们代码就是有问题了。 

void InsertSort(int* arr, int n)
{for (int i = 0; i < n - 1; ++i){//记录有序序列最后一个元素的下标int end = i;//待插入的元素int tem = arr[end + 1];//单趟排while (end >= 0){//比插入的数大就向后移if (tem < arr[end]){arr[end + 1] = arr[end];end--;}//比插入的数小,跳出循环else{break;}}//tem放到比插入的数小的数的后面arr[end + 1] = tem;//为什么写在外面,这是因为防止我们后面有一个最小的数,如果写在里面的话,那么end会减到-1.那么就跳出循环了,无法交换。所以写在外面是防止这样的情况//代码执行到此位置有两种情况://1.待插入元素找到应插入位置(break跳出循环到此)//2.待插入元素比当前有序序列中的所有元素都小(while循环结束后到此)}
}

7c07b8b4340540818b56acd4878f8ba6.png

        这是我设的一个插入排序的一个示例。当然这些里面的势力还算比较简单的,还不足以体现插入排序的优势。但是大家知道冒泡排序是我们六大排序中速度最慢的。我们学会了插入排序,后面如果对希尔排序,如果不了解的话,插入排序也算是一个较好的排序方法。 

      补充:我想大家可能会对代码中的有一个有疑问,就是为什么插入的数大于的话后移,后要end减减嘞。这个是因为我们排序就是下标为1的与下标为0的对比然后交换。是从后向前交换,与冒泡排序的从前往后交换。所以我们第一次是只交换一次。并且大家需要注意的是我在上面还的代码中的,为什么将arr[end + 1] = tem;写在外面。

希尔排序思路

        对于希尔排序来说啊,这其实超过了我们普通人或一般学霸的认知了。其实虽然我们有想可能会想过对一些很混乱的数组我们先给他排简单排一下,然后再进行排序。但是我们简单排序,怎么给他简单排序了?而且反正都要排序的。那不是浪费更多的时间吗?反正这是我个人是这么想的。他也正是因为我们都能想到可以给它初排序一下。但是我们初排序是如何排的呢?我们却并没有想过。但是希尔他就想过了。他想将一个数组用gap(一个数)来个开。就好比是下面这个样子。df89755290ad478c8f849e17f731272b.png

        然后我们以两个节点来对比进行交换。而且我们再将移动到下一个下标。并且也以gap隔离来进行节点交换,这样就完成了我们的初排序。大家可以想象这样是不是就形成了一个相对比较有序的数组?ed9afe30a0c74883976110e39593c2b1.png

        但是大家也知道,我们这个开始想的也就是初排序。我们还需要一个实际排序呀。那么就要用我们上面写的插入排序了。我们插入排序是与下一个进行对比,那我们希尔排序中间隔了gap后再进行对比交换的。那么不知道大家是否要联想到希尔排序与插入排序为基础来实现写的? 

        好了,我们初入排序写了,那么我们接下来该怎么操作呢?我们每一次单趟的gap是确定的。那么如果我们这样第二堂的gap设为第一堂gap的3分之一。那么我们是不是就会比较细一点了?但是我们想想是不是有时候有些时候被3初了会为零,不会为1。那么我们就没有再具体走一遍,是吧?所以我们在除以下之后再加一,那么我们是不是就能保证最后一次为1了。这样我们是不是就最后将整个排序实现了。

14637ac288f0449e9f239d7a77da2e78.gif

希儿排序实现 

       那么上面我们居然写了大概思路。我们还是想插入排序一样,先写单趟如何实现。

void ShellSort(int* arr, int size)
{int gap = 3;int i = 0;for (i = 0; i < size - gap; i++)	//从0遍历到size-gap-1{//为什么是小于size-gap。因为当我们size本来就大于数组个数一个,减去gap后的数就是临界点了,再加一个gap的话就超界了。大家可以想想。int end = i;//是不是就是插入排序啊int temp = arr[end + gap];while (end >= 0){if (arr[end] > temp){arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = temp;	//以 end+gap 作为插入位置}
}

       不知道大家看到这个是我觉得很熟悉啊,是不是?像我们上面写的插入排序?就是将插入排序中的一改为了gap。是不是就实现了我们说的gap节点,然后进行对比交换了。 那么我们实现了单次排序之后,我们下一次排序。我们在上面说过gap是会变的。一直到为1就成为最后的插入排序,这个大家了解吧。那么就简单了,我们只需要再写一个循环,在循环的时候这样每一次gap进去之后进行改变。

void xixi(int* arr, int size)
{int gap = size;while (gap > 1){gap = gap / 3 + 1;//没进行一次gap后,gap进行改变int i = 0;for ( i = 0; i < size - gap; i++){int end = i;int tmp = arr[end + gap];while (end >= 0){if (arr[end]>tmp){arr[end + gap] = arr[end];end-=gap;}else{break;}}arr[end + gap] = tmp;}}
}

        这样大家应该能了解了吧。希尔排序简单一点,也就是说我们先以gap为跨点进行一次大的排序,然后再依次减少,依次减少。这样原本乱序的数组就成为了相对有序的数组。最后我们就直接用插入排序,那样是不是就解决了这个问题了?

         所以大家只需要理解,我们先出了gap为1以前的都叫预处理。为1之后就是正式的排列了。  当然希尔排序其实是有一点困难的,大家需要多理解一点多看一下,其实相对还是比较简单的,只需要理解之后大家都能写出来的。

总结     

        好了,以上就是本篇博客想与大家分享的两个排序方法的。大家可以先着重了解插入排序,因为希尔排序是以插入排序为基础而推进发展的。当然如果大家对希尔还是不太了解的话,插入排序现在对目前来说还是很有用的,先了解他的话也是足够了的。好了,本篇博客肯定还有很多不足的地方,希望大家能在评论区留言,方便鄙人来更改。

 

 

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

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

相关文章

618必买的数码好物有哪些?盘点兼具设计与实用的数码好物分享

随着618购物节的到来&#xff0c;数码爱好者们又开始跃跃欲试&#xff0c;期待在这个年度大促中寻找到自己心仪的数码好物&#xff0c;在这个数字化时代&#xff0c;数码产品不仅是我们日常生活的必需品&#xff0c;更是提升生活品质的重要工具&#xff0c;那么在众多的数码产品…

HNU-计算机体系结构-实验1-RISC-V流水线

计算机体系结构 实验1 计科210X 甘晴void 202108010XXX 1 实验目的 参考提供为了更好的理解RISC-V&#xff0c;通过学习RV32I Core的设计图&#xff0c;理解每条指令的数据流和控制信号&#xff0c;为之后指令流水线及乱序发射实验打下基础。 参考资料&#xff1a; RISC-…

Ubuntu20.04升级到22.04之后出现的问题

项目场景&#xff1a; 之前一致使用的是Ubuntu20.04&#xff0c;虽然丑了点&#xff0c;但是用着没什么问题&#xff0c;最近没能按捺住好奇心&#xff0c;升级到了22.04&#xff0c;升级后颜值有所提高&#xff0c;但是也带来了一些问题。 从20.04升级到22.04&#xff0c;起始…

sendmail发送邮件配置详解?如何正确设置?

sendmail发送邮件如何保障安全&#xff1f;AokSend有何安全措施&#xff1f; 为了确保sendmail发送邮件的高效性和安全性&#xff0c;正确配置是至关重要的。本文将详细介绍sendmail发送邮件的配置步骤&#xff0c;并探讨如何保障sendmail发送邮件的安全性。同时&#xff0c;我…

界面控件DevExpress WinForms的流程图组件 - 可完美复制Visio功能(一)

DevExpress WinForms的Diagram&#xff08;流程图&#xff09;组件允许您复制Microsoft Visio中的许多功能&#xff0c;并能在下一个Windows Forms项目中引入信息丰富的图表、流程图和组织图。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows F…

2024年中国金融行业网络安全研究报告

网络安全一直是国家安全的核心组成部分&#xff0c;特别是在金融行业&#xff0c;金融机构拥有大量的敏感数据&#xff0c;包括个人信息、交易记录、财务报告等&#xff0c;这些数据的安全直接关系到消费者的利益和金融市场的稳定&#xff0c;因此金融行业在网络安全建设领域一…

成都市酷客焕学新媒体科技有限公司:助力品牌打破困境!

在数字化浪潮的推动下&#xff0c;营销策略对品牌的发展愈发关键。成都市酷客焕学新媒体科技有限公司&#xff0c;作为短视频营销领域的佼佼者&#xff0c;凭借其卓越的策略和实力&#xff0c;助力众多品牌在信息海洋中脱颖而出&#xff0c;实现品牌的显著增长。 酷客焕学专注于…

部署八戒-Chat-1.8B 模型

1 简单介绍 八戒-Chat-1.8B 八戒-Chat-1.8B是运用 InternLM2-Chat-1.8B 模型进行微调训练的优秀成果。其中&#xff0c;八戒-Chat-1.8B 是利用《西游记》剧本中所有关于猪八戒的台词和语句以及 LLM API 生成的相关数据结果&#xff0c;进行全量微调得到的猪八戒聊天模型。作为 …

python-使用API

python-使用API 使用github的api-即url地址请求数据 https://api.github.com/search/repositories?qlanguage:python&sortstars #这个调用返回GitHub当前托管了多少个Python项目&#xff0c;还有有关最受欢迎的Python仓库的信息。在浏览器中输入上面地址可以看到该接口&…

论文《Sensor and Sensor Fusion Technology in Autonomous Vehicles: A Review》详细解析

论文《Sensor and Sensor Fusion Technology in Autonomous Vehicles: A Review》详细解析 摘要 该论文对自动驾驶汽车中的传感器和传感器融合技术进行了全面回顾。它评估了各种传感器&#xff08;如相机、LiDAR、雷达&#xff09;的能力和技术性能&#xff0c;并讨论了多传感…

fastadmin部署后JSHint报错,导致Config::getValueByName()无法获取到值

问题 解决方案 一、本地 在phpstorm中&#xff0c;依次点击【设置】-【JSHint】-【取消勾选Enable】-【应用】即可。

无需安装的在线PS:打开即用

为什么想用在线PS网页版&#xff1f;Photoshop常用于平面设计&#xff0c;是不少设计师接触过的第一款设计软件。作为一款平面设计工具&#xff0c;ps功能太多&#xff0c;并且没有在线版&#xff0c;这不仅需要设计师花费时间学习软件&#xff0c;还需要设计师具备一定的设计能…

正邦科技(day2)

自动校准 问题&#xff1a;电量不准都可以直接去校准 校准方式&#xff1a;可程式变频电压 问题分析&#xff1a;他是通过软件去自动自动校准的&#xff0c;flash 清空的时候有缓存没有清空&#xff0c;或者互感器没有读取到问题 互感器&#xff1a;电流互感器的作用包括电流测…

【DrissionPage爬虫库 1】两种模式分别爬取Gitee开源项目

文章目录 DrissionPage爬虫库简介1. 浏览器操控模式&#xff08;类似于游戏中的后台模拟鼠标键盘&#xff09;2. 数据包收发模式&#xff08;类似于游戏中的协议封包&#xff09; 实战中学习需求&#xff1a;爬取Gitee开源项目的标题与描述解决方案1&#xff1a;用数据包方式获…

SSL证书:守护个人信息安全的坚固盾牌

在数字化浪潮汹涌的今天&#xff0c;我们的个人信息如同一座座宝藏&#xff0c;吸引着不法分子的贪婪目光。数据泄露事件频发&#xff0c;让信息安全问题日益凸显。而在这个信息爆炸的时代&#xff0c;如何保护我们的个人信息安全&#xff0c;成为了一个亟待解决的问题。幸运的…

股票量化交易上手,一个特别简单却长期可用的交易策略,官方接口

股票实现程序化自动化交易的三个基础&#xff1a;获取数据、执行交易、查询账户。 以后说到策略示例的时候就不介绍接口的基础使用方法了&#xff0c;随便一个策略把过程写出来都会很啰嗦&#xff0c;尽量压缩内容吧&#xff0c;这些内容是面向新手的&#xff0c;大佬们忽略细节…

qq音乐sign逆向

qq音乐sign参数逆向 1.概览 参数sign长度40 多次调试发现&#xff0c;前缀zzb不变 2.打日志 跟站发现是vpm&#xff0c;在apply调用打上日志断点&#xff1a; 连蒙带猜知道&#xff0c;最终字符串四部分构成&#xff0c;zzb 24DC2798 HI0TvE4tOMqzN4w88oZCjQ EE0A88FE 1.把…

C++第二十一弹---vector深度剖析及模拟实现(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、基本结构 2、默认成员函数 2.1、构造函数 2.2、析构函数 2.3、拷贝构造函数 2.3、赋值操作符重载 3、数据访问 4、迭代器获取 总结 …

数字经济与资本市场的密切关系!

数字经济的崛起&#xff0c;如同一股强劲的东风&#xff0c;吹拂着经济社会的每一个角落&#xff01;它带来了“新领域”和“新赛道”&#xff0c;赋予了“新动能”和“新优势”&#xff0c;成为引领中国经济增长和社会发展的重要力量。如今&#xff0c;发展数字经济已上升为国…

人人都是产品经理,尼恩产品经理面试宝典(史上最全、定期更新)

《人人都是产品经理&#xff0c;尼恩产品经理面试宝典》&#xff08;史上最全、定期更新&#xff09; 本文版本说明&#xff1a;V1 IT不老新物种 的定义 大龄男IT &#xff1a;APM 架构经理 项目经理 高级开发&#xff0c;没有中年危机 大龄女IT&#xff1a;DPM 产品经理 …