插入排序与希尔排序(C语言实现)

news/2025/3/14 1:02:49/

1.插入排序

由上面的动图可以知道插入排序的逻辑就是从第一个元素开始往后遍历,如果找到比前一个元素小的(或者大的)就往前排,所以插入排序的每一次遍历都会保证前面的数据是有序的,接下类用代码进行讲解。

我们这里传两个参数,一个是数组,一个是数组元素的个数。

排序接口我们采用大事化小的想法来进行讲解, 我们先来思考单趟遍历要达成的目标。我们每次遍历的主角其实就是我们要操纵的那一个元素,比如我们要排第四个元素,按照插入排序的逻辑,前三个元素我们是已经有序了,所以我们接下来的操作就是将我们的主角元素跟前面的元素进行比较,如果元素比前面的小我们就跟前面的交换(我们这里实现升序排序),以此循环往复,直到遇到比它还小的元素我们就终止循环,所以我们就可以理解里面这层while循环的意思了,循环结束的时候不要忘记把元素放到停止循环的end下标位置上,有的同学可能一时间没有理解到为什么最后下标的位置是end+1,其实这是因为在结束while循环之前我们的end是减一过的,所以才要给他加回去。

然后我们的for循环就是控制我们的主角啦,就是控制后面的每一个元素跟前面已经排序好的元素进行比较。

插入排序最坏的时间复杂度O(n^2)

最好的情况就是这个数组已经有序的时候时间复杂度为O(n)

2.希尔排序

 上诉动态演示就是希尔排序,大家看到这个演示的时候肯定会两眼一黑,看不懂它是如何进行排序的,希尔排序的逻辑是有点复杂,但是我相信在我讲了它的实现思路之后对希尔排序也会有一个比较清晰的理解。

希尔排序可以相当于插入排序的pro版本,这是因为它的逻辑虽然比插入排序复杂,但是却是建立在插入排序之上,插入排序的核心思想是遍历每一个元素去跟前面已经排好序的元素进行比较,希尔排序有一个预排序的过程,就是说通过给定一个gap(变量名)来控制一个间距,使下标为end的元素跟end+gap来比较,这个预排序就是使一个无序数组接近有序数组,在预排序完成之后再用插入排序使数组有序。其实到这里大家就会发现,如果用这里的思想去理解插入排序的话,插入排序实际上就是gap为1的情况嘛。

我们用代码来加深理解。

这是希尔排序的代码,我们可以看到gap的初始值设置的是数组的长度,那下面的while循环时什么意思呢?我们先来理解最里层的while循环,最里层的while循环是不是有一种很眼熟的感觉?它就是我们的插入排序的思想,只不过插入排序是间隔为一进行比较,希尔排序是间隔为gap进行比较,我们再看外面这层for循环,这层for循环控制的就是end的下标,跟插入排序也非常的相似,只不过这里的for循环结束的条件是n-gap,因为既让我们当前下标的元素要跟后一个相比,那总不能让end+gap的下标超出界限吧。

最后再来看最外层的while循环,它的作用就是控制gap的值。我们这里得要知道gap越大,这一趟预排序就越不能做到很有序的程度,但好处就是耗时短,gap的值越小就是相反的情况,但是不要忘记了,一个数组越有序,插入排序处理得就越快,希尔排序也是一样的,所以为了达到理想的时间复杂度,我们的做法就是将gap的值由大到小。

接下来来说说gap的值如何来设置,gap的值该如何来设置是没有一个统一的说法的,但是有一个大佬想出的一个比较好的方法是用数组长度来充当第一次的gap值,每一次循环完就将gap的值/3+1这是为了避免上一个gap为二的时候下一次gap直接变为0了。

所以我们的希尔排序最后一趟就是我们的插入排序,只不过这个时候数组已经非常接近有序了。

我们的希尔排序最坏的情况下时间复杂度是O(n^2),平均是O(n^1.3)。


http://www.ppmy.cn/news/1263243.html

相关文章

STM32F1之CAN介绍

目录 ​编辑 1. CAN 是什么? 2. 总线拓扑图 3. CAN 的特点 4. CAN 协议的基本概念 1. CAN 是什么? CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO*1 国际标准化的串行通信协议。 在当前的汽车产…

ElementUI 时间选择器如何限定选择时间

DatePicker 日期选择器 | Element Plus 我们如何限定我们的选择时间呢,比如限定选择时间为今天之前,或者今天之后的时间? 我们可以使用官方提供的disabled-date来实现 我们通过这个属性 做一个回调函数,在里面比较我们想要限定的时…

网神SecGate 3600防火墙 app_av_import_save接口任意文件上传漏洞复现 [附POC]

文章目录 网神SecGate 3600防火墙 app_av_import_save接口任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现0x06 修复建议网神SecGate 3600防火墙 app_av_import_save接口任意文件上传漏洞复现 [附PO…

Python:核心知识点整理大全9-笔记

目录 ​编辑 5.2.4 比较数字 5.2.5 检查多个条件 1. 使用and检查多个条件 2. 使用or检查多个条件 5.2.6 检查特定值是否包含在列表中 5.2.7 检查特定值是否不包含在列表中 banned_users.py 5.2.8 布尔表达式 5.3 if 语句 5.3.1 简单的 if 语句 5.3.2 if-else 语句 …

Redis Geo操作地理位置

Redis Geo 使用场景API列表名词API列表Springboot使用mavenyamlTest 注意事项 Redis Geo 是Redis在3.2版本中新增的功能,用于存储和操作地理位置信息 使用场景 滴滴打车:这是一个对地理位置精度要求较高的场景。通过使用Redis的GEO功能,滴滴…

C/C++指针操作整理

C/C指针操作整理 面向曾经学习过指针的人,并非针对究极初学者。 一维指针 数据类型存储的地址,指向数据存储的地址,可以使用 &运算符取变量的地址,将其赋给指针变量。 int a 2; int *p &a;同时因为C/C中数组是连续存储…

举例C#使用特性排除某些类成员不参与XML序列化和反序列化

在C#中,可以使用 [XmlIgnore] 特性来排除某些类成员不参与XML序列化和反序列化。这个特性告诉XML序列化器忽略被标记的成员。 以下是一个使用 [XmlIgnore] 特性的示例: using System; using System.IO; using System.Xml.Serialization;public class P…

Ubuntu编译文件安装SNMP服务

net-snmp源码下载 http://www.net-snmp.org/download.html 编译步骤 指定参数编译 ./configure --prefix/root/snmpd --with-default-snmp-version"2" --with-logfile"/var/log/snmpd.log" --with-persistent-directory"/var/net-snmp" --wi…