因为简单插入排序中存在一些问题( 这里我们以升序排序为例 ): 当我们要待插入的数值比较小时后移的次数明显增多,对效率有比较大的影响,所以我们就提出了希尔排序
希尔排序是希尔(Donald shell)于1959年提出的一种排序算法,希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更加高效的版本 , 也称之为 : 缩小增量排序
希尔排序是把记录按下标的一定增量分组,对每个组使用直接插入排序算法进行排序,随着增量主键减小,每组中包含的关键词越来越多,当增量减少到1的时候,整个就会被分为一组,然后就对这一组进行一次直接插入排序,然后算法变终止了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6IAVrS7-1661005216498)(E:\非凡英才\数据结构(java)]\数据结构图解\插入排序过程图解.png)
这个就是因为我们的直接插入排序也是有这两种方式,但是我们一般都是使用位移式,不会选择使用交换式,因为交换式和冒泡排序有些类似,执行效率太低,所以我们一般都是使用的位移式,所以这里我们也就是对位移式的希尔排序进行一个讲解
我们首先要知道希尔排序算法的实现是要通过三层for循环来实现的,因为我们的希尔排序就是在每次分组的基础上进行一个直接插入排序,而直接插入排序我们要使用两层循环(外层for循环 + 内层while循环)来解决,而对于我们的分组,也就是自增变量的缩小我们也要通过一层for循环来实现
我们定义的gap变量就是表示我们希尔排序中的增量,增量其实也就等于分的组的个数,我们的增量是在length/2之间的,包括length/2和1,所以这个时候我们判断分组退出的条件就是当我们的gap(增量) = 0,这个时候等于0就会退出,那么我们就要让这个循环的判断条件为gap>0,这个时候如果gap=0的时候就会退出循环了
希尔排序中要定义的变量和我们的直接插入排序中定义的变量是一样的,因为我们的希尔排序就是在分组的基础上进行了一个直接插入排序
也就是我们的希尔排序中也是定义如下两个变量:
int insertVal = 0; //这里只是定义,但是赋值的时候insertVal也是应该等于0的,但是我们在我们后续的算法中将insertVal的值赋值为了gap,这个时候沃恩的insertVal就不是表示我们的待插入位置的前一个位置,而是直接就是我们的待插入位置
int insertIndex = 0: //这里只是定义,具体赋值的时候我们是将insertIndex的值赋值为: gap
希尔排序就是在直接插入排序的基础上做了一个升级, 我们之前讲过: 简单直接插入排序算法的缺点就是当我们的待排序序列趋于逆序的时候这个时候我们要做的位移或者交换就会有很多次, 效率就会比较低(这里说的位移就是直接将元素后移, 交换就是将元素的位置交换), 如果是使用的交换式的直接插入排序, 如果是遇到完全逆序的情况, 其时间复杂度会和冒泡排序差不多, 都是非常低的, 所以为了解决这个问题, 为了能一定程度的提高直接插入排序算法的时间复杂度, 我们就在简单直接插入排序的基础上提出了希尔排序
希尔排序就是一个逐渐缩小增量的直接插入排序, 就是先将整个待排序序列分成多个序列, 然后在每个序列中进行一个直接插入排序, 然后最终增量将会一直缩小, 直到最终的时候我们的增量会缩小到1, 这个时候我们的序列就会是整个的一个序列, 那么这个时候我们进行一个简单直接插入排序的时候由于我们的序列的混乱度比较低, 这个时候算法(也就是我们的简单直接插入排序的算法时间复杂度就会很高)