【排序算法】第一章:插入排序----直接插入排序与希尔排序的详解和对比

devtools/2024/9/23 6:28:13/

🫡和我一起感受 两种排序算法的魅力吧!
在这里插入图片描述

前言:

理解排序算法最好的方法就是:先单趟后整体

  • 先从一个元素的一趟开始理解
  • 再扩展到所有元素的排序

一、直接插入排序

理解排序算法最好的方法就是:先单趟后整体

插入排序:以升序排序为例
总体思路

  1. 一个元素向前比较,遇到比自己大的元素,该较大元素就向后移动一位
  2. 遇到前一个元素比自己小,则自己就在当前位置插入(就是前一个元素的下一个位置)

单趟逻辑

int end; // end 代表前一个元素下标
int tmp = a[end + 1]; // tmp 就是当前要向前比较的当前元素
while (end >= 0)
{if (a[end] > tmp) {   // 遇到比自己大的元素,a[end + 1] = a[end];  // 该较大元素就向后一位,end--;  // 同时下标前移}else break; // 当自己大于或等于前一个元素时,自己可以插入当前位置了
}
a[end + 1] = tmp;  // 插入在当前位置

在这里插入图片描述

在这里插入图片描述


整体逻辑:所有元素排序

由单个元素排序逻辑可知:可以同时表示当前元素和前一个元素的,就是 end
则 需要循环 end,使每一个元素可以遍历到
由动图可知,end 最多可以到达的位置为 n - 2(数组从 0 开始),因为最后一个元素的位置在 n - 1,而 end+1 必须合法(若 end == n-1,则 end+1 == n, 越界了 )


注意:插入排序是从前向后循环 end 的
不能从后往前:前面的序列不是 有序的,插排无效
插入排序需要保证自己当前元素的前面序列全部有序
其中 end 从 0 开始,第一个真正开始比较的元素是 end + 1,这里默认 数组首元素已经算作有序

动图演示

在这里插入图片描述

// 外层 for,循环 end
for (int i = 0; i < n - 1; ++i) {int end = i;  // end 每轮为 iint tmp = a[end + 1]; // tmp 就是当前要向前比较的自己while (end >= 0){if (a[end] > tmp) {   // 遇到比自己大的元素,a[end + 1] = a[end];  // 该较大元素就向后一位,end--;  // 同时下标前移}else break; // 当自己大于或等于前一个元素时,自己可以插入当前位置了}a[end + 1] = tmp;  // 插入在当前位置
}

时间复杂度计算

计算时间复杂度:
当元素全部逆序时为最坏情况
排序次数和为 1 + 2 + 3 + 4 + … + n 成等差数列
由等差数列公式求和得出: (n^2 + n) / 2
时间复杂度就是 O(n^2) 级别的

==最好情况是顺序:O(n) ==

启发:当一个序列基本有序时,使用插排可以 有接近 O(n) 的时间复杂度

二、希尔排序

希尔排序是对直接插入排序的优化,建议先学了 直接插入排序 后再来学这个,否则较难理解

希尔排序可以说是对插入排序的一种升华,一种升级版插入排序通过 预排序 使局部有序率放大,从而便于提高插入排序效率,具体下面解释:

效率优化的具体原理:

由于插入排序在序列有序时,效率较高,希尔就通过这个特性,设计一种算法,使待排序的序列接近有序、

观察
直接插入排序:可以发现,有一些较大的值,本身最终就是要排序到末尾位置的,而这个值偏偏又在序列前面,还要一点一点的挪动,中间浪费的较多的时间

则这部分时间就可以优化掉,这就是希尔的思路

希尔排序会 进行 预排序:分组插入排序

目的:将较大值更快的放到后面的位置,较小值更快的放大前面位置




动图演示

可以看到每次数据进行交换 都是和自己同一颜色的进行交换,这就是 分组进行插入排序

分组依据:设置 gap 间隔,动图为例,每个数据间隔位置为 gap == 5 ,最多不超过 第 n-1 个

在这里插入图片描述

循环对每一组数据插入排序

代码如下:

int gap = 5;
for (int i = 0; i < n - gap; i += gap) {int end = i;int tmp = a[end + gap];while (end >= 0) {if (a[end] > tmp) {a[end + gap] = a[end];end -= gap;}else break;}a[end + gap] = tmp;
}

可以发现,该代码和 前面讲解的 直接插入排序 一摸一样😋

没错,前面讲解的 直接插入排序 属于 gap == 1 的情况,间隔为 1,则每一个数据都是 “ 一组”

希尔排序 这里就是 gap > 1 的情况,只需要将 前面讲解的 直接插入排序 的代码中 的 某部分的 1 改成 gap 就好




前言:gap > 1 的排序称为 预排序,都是为最后一次 gap == 1 排序服务

其实希尔排序也可以说是对插入排序的一种升华,我们有提到插入排序的效率大于冒泡排序,是因为它有较好的局部有序性,那么希尔排序就是对这一优势的放大,使局部有序性加大

预排序 会将数组 局部有序率放大到极高,所以最后一次插入排序的时间复杂度很低,则极大提升效率

进行完一次 gap == 5 的排序后,各小组内部已经有序了,但是 小组之间还未有序,则需要缩小 gap 再次进行比较

在这里插入图片描述

后续需要缩小 gap 再次比较,那 gap 应该以什么规律缩小,同时需要满足最后可以缩小至 gap == 1,进行最后一次?

方案:每轮减半,最后 gap == 1 可以进行最后一次

int gap = n;
while (gap > 1) {gap = gap / 2;// ..... 
}

希尔排序第二轮:gap = gap / 2 = 2

在这里插入图片描述

希尔排序最后一轮:gap = gap / 2 = 1
在这里插入图片描述




最终代码:

int gap = n;
while (gap > 1) {gap = gap / 2;///for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0) {if (tmp < a[end]) {a[end + gap] = a[end];end -= gap;}else break;}a[end + gap] = tmp;}///}

总结:

gap == 1 就是直接插入排序 gap > 1 就是希尔排序

希尔排序的时间复杂度不好计算,因为 gap 的取值方法很多,导致很难去计算




直接插入排序希尔排序的性能对比

下面我用代码随机生成 1000000 个数据,执行两个排序算法,显示的数据为 代码运行时间,以 ms 为单位

在这里插入图片描述

🤣直接插入排序 直接执行了 约 2min,而 希尔排序只有 89 ms !!!!!

😎怎么样,是不是惊呆了,这个差距相当大了,这里不得不佩服 希尔大神!!!




🫡至此,第一章完结!

【若文章有什么错误或则可以改进的地方,非常欢迎评论区讨论或私信指出】**


http://www.ppmy.cn/devtools/22798.html

相关文章

学习STM32第二十天

低功耗编程 一、修改主频 STM32F4xx系列主频为168MHz&#xff0c;当板载8MHz晶振时&#xff0c;系统时钟HCLK满足公式 H C L K H S E P L L N P L L M P L L P HCLK \frac{HSE \times PLLN}{PLLM \times PLLP} HCLKPLLMPLLPHSEPLLN​&#xff0c;在文件stm32f4xx.h中可修…

免费分享一套SpringBoot企业人事管理系统(员工管理,工资管理,档案管理,招聘管理),帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBoot企业人事管理系统(员工管理&#xff0c;工资管理&#xff0c;档案管理&#xff0c;招聘管理)&#xff0c;分享下哈。 项目视频演示 【免费】SpringBoot企业人事管理系统(员工管理&#xff0c;工…

分布式与一致性协议之CAP(三)

CAP ACID理论:CAP的"酸"&#xff0c;追求一致性。 提到ACID,它很容易理解&#xff0c;在单机上实现也不难&#xff0c;比如可以通过锁、时间序列等机制保障操作的顺序执行&#xff0c;让系统实现ACID特性。但是一说要实现分布式系统的ACID特性比较难实现呢&#xf…

生成对抗网络的无载体信息隐藏算法简介

一、研究背景 随着互联网技术的广泛应用和移动智能设备的快速普及&#xff0c;人们有了更多的途径传播和获取信息。每天海量的数据以视频、音频、图像、文字等各类形式在互联网中产生&#xff0c;这为人们的生活带来了极大的便利&#xff0c;但同时也引起了人们对信息泄露的担…

【prometheus】k8s集群部署AlertManager实现邮件和钉钉告警

目录 一、AlertManager概述 1.1 alertmanager简介 1.2 AlertManager核心概念 1.2.1 分组 1.2.2 抑制 1.2.3 静默 1.2.4 客户的行为 1.2.5 高可用性 二、Alertmanager部署邮箱告警 2.1 邮箱配置 2.2 Alertmanager global和route路由配置 2.3 部署prometheus和alertM…

【c++】【贪心】排队接水

排队接水 题目难度&#xff1a;中阶 时间限制&#xff1a;1000ms 内存限制&#xff1a;128MB 题目描述 有 n 个人在一个水龙头前排队接水&#xff0c;假如每个人接水的时间为 Ti&#xff0c;请编程找出这 n 个人排队的一种顺序&#xff0c;使得 n 个人的平均等待接水时间最…

中信银行深耕养老金融,构建多支柱养老金体系新格局

在应对人口老龄化这一全球性挑战的过程中&#xff0c;养老金融已成为中国金融领域的重要篇章。2024年4月25日&#xff0c;中信银行行长刘成在财新传媒主办的“2024中国养老产业论坛”上发表主旨演讲&#xff0c;深入阐述了养老金金融、养老服务金融、养老产业金融互促互进的大趋…

Hibernate:Caused by: java.lang.ClassNotFoundException: oracle.sql.BLOB

在spring里插入 BLOB字段 kp.setContent(content.getBytes()) 方法 &#xff1a;hibernate saveOrUpdate 报 Caused by: java.lang.ClassNotFoundException: oracle.sql.BLOB 使用tomcat 没问题&#xff0c;可服务器改为 WebSphere .就报错。 把Spring内置提供的NativeJdb…