直接插入排序和希尔排序

大家好!这篇我们就说一下排序中的两种插入排序。
在这里插入图片描述

1. 直接插入排序

1.1 基本思想

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

1.2 思路流程

假设,我们有这样的一组数字:
在这里插入图片描述
我们把第一个数看成有序,把第二个数插入进去:
在这里插入图片描述
这时,我们将1存到一个变量里,然后和前面的数比较,如果比它小就继续往前,如果不是,就放在它后面。
这里,1比9小,我们将9移到后面,把1放到0位置处。
在这里插入图片描述
此时,前两个数有序,我们将第三个数插入进去,2比9小,将9往后移,然后和1比,比1大,就放在1后面。
在这里插入图片描述
这样,前三个数就有序了,再把第4个数插入进去,依次类推。
动态流程图如下:
在这里插入图片描述

1.3 具体实现

首先,我们先实现一趟的排序:
在这里插入图片描述

假设,我们要将3插入进去,我们可以定义一个end指向最后一个数,将end+1的数插入,如果比end小,就一直往前移,如果比end大,就直接放在end后面。
在这里插入图片描述
这里要注意一个问题:
如果这里,我们要插入一个0呢?
在这里插入图片描述
0比1小,end–就会到下标-1处,但此时0还没有放到下标为0处的地方,所以我们可以这样去修改:
在这里插入图片描述
这里的end我们应该给什么呢?
在这里插入图片描述
首先,end为0,插入第二个数,然后end为1,插入第三个数,依次类推
在这里插入图片描述
当end为n-2时,就插入最后一个数。
完整代码如下:
在这里插入图片描述

1.4 时间复杂度

我们来看一下直接插入排序的时间复杂度:
最坏:逆序O(N^2)
最好:顺序有序O(N)

然后,我们来看一下以前说过的冒泡排序:
在这里插入图片描述
它的时间复杂度为:
最坏:逆序O(N^2)
最好:因为不知道顺序有序,还是要进行一次次的比较,所以时间复杂度:O(N^2)

我们可以改进一下冒泡排序:
在这里插入图片描述
这样的话,如果顺序有序一轮循环后,flag还是0,这样循环就结束了。
所以时间复杂度为O(N)。

那我们就用直接插入排序和冒泡排序比较一下:
在这里插入图片描述
我们来看直接插入排序比较的次数为:8次
冒泡排序的比较次数为:7+6=13次

那么我们就可以得出结论:
如果顺序有序,那么插入和冒泡是一样的。
但是如果是局部有序,或者接近有序,那么插入适应性和比较次数更少。

2. 希尔排序( 缩小增量排序 )

2.1 基本思想

希尔排序分为两步:
1.预排序
2.直接插入排序

什么是预排序呢?
大的数更快的到后面,小的数更快的到前面,接近有序。
如何预排序呢?
1.先选定一个整数gap,每组数据间隔为gap为一组,所以gap为几,就会分为几组数据。
2.分别使用插入排序的思想对这gap组数据进行排序。

2.2 思路流程

在这里插入图片描述
假设,我们就用这组数据,假定gap为3。那么我们可以分成以下几组:
在这里插入图片描述
然后,用插入排序的思想对这gap组数据进行排序。
我们假设9是有序的,然后把5插入,5比9小,所以交换位置。
在这里插入图片描述
这样,5和9就有序了,然后我们将8插入进去,8比9小,9往后移,8比5大,就放在5后面。
在这里插入图片描述
这样,5,8,9都有序了,然后我们将5插入进去:
在这里插入图片描述
其它组也是一样的道理,最后的情况如下:
在这里插入图片描述
它就会比原来的数组更加有序。
那么我们可以得出一些结论:
如果gap越小,越接近有序。
如果gap越大,大的数据可以更快到最后,小的数可以更快到前面,但它越不接近有序。

那么gap一般给多少呢?
我们可以看出gap跟n是有关联的,n越大,gap应该大些,n越小,gap应该小些,所以一般我们建议是n/3

2.3 具体实现

我们首先来写一趟预排序:
在这里插入图片描述
我们以gap为3为例。
在这里插入图片描述
那么这里的end我们该如何赋值呢?
我们可以看出,end首先在0处,然后0+gap位置,然后在0+gap+gap,一直到n-1-gap处。
在这里插入图片描述
这是黑色的那一组,那我们要控制三组,蓝色的那组是从1开始,红色是从2开始,所以我们还要加一层循环。
在这里插入图片描述
这样的代码,我们可以改进成两层循环:
在这里插入图片描述
第一种是一组一组排,第二种是黑色组第一个排,然后是蓝色组第一个排,分开排。
然后,我们要加一层循环来控制gap,让它变得接近有序:
在这里插入图片描述
这里的+1的意思是让gap最后为1,就是直接插入排序,让它变为顺序有序。

2.4 时间复杂度

那我们来看看这希尔排序到底怎么样呢?
在这里插入图片描述
首先,我们来看一下这个红色框预排序的时间复杂度。
当gap很大时,数据跳的很快,里面那层循环就可以忽略不计。差不多是O(N)。
当gap很小时,因为很接近有序,差不多也是O(N)。

然后,我们看一下外面那层循环次数:
在这里插入图片描述
这里,我们把1忽略掉,所以就是:
n/3/3/3/3…=1,假设除了x的3,所以n=3^x,x等于以3为底的logN
所以,经过我们粗略的计数,希尔排序的时间复杂度为:
N*log3N

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定:
有人在大量的实验基础上推出一个平均值:O(N^1.3)

到这里,插入排序就结束了,如果大家觉得有帮助,可以多多支持!感谢大家!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学代码的咸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值