大家好!这篇我们就说一下排序中的两种插入排序。

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)
到这里,插入排序就结束了,如果大家觉得有帮助,可以多多支持!感谢大家!

2612

被折叠的 条评论
为什么被折叠?



