思想
希尔排序大概就是,选一组递减的整数作为增量序列(也就是步长)。最小的增量必须为1:DM>DM−1>...>D1=1DM>DM−1>...>D1=1
- 先用第一个增量把数组分为若干个子数组,每个子数组中的元素下标距离等于增量;
- 然后对每个子数组进行一次插入排序
- 再使用第二个增量,继续同样的操作,直到增量序列里的增量都使用过一次。
(增量为1时,就是对整个数组进行一次插入排序)
图解
看图更容易理解吧:
(慕课的浙大数据结构)
性能
希尔排序快不快主要取决于我们怎么取“增量序列”,原始希尔排序的取法就是:DM=⌊N/2⌋,Dk=⌊Dk+1/2⌋DM=⌊N/2⌋,Dk=⌊Dk+1/2⌋
此增量序列也称为Shell增量序列
原始希尔排序最坏的时间复杂度为O(n2)
代码实现
(最原始的实现有四重循环,不太简洁,下面的实现是优化后的,通过改变初始索引淡化了分组的那一层循环)
public static void shellSort(int[] arr) {
int h = arr.length>>1;
while(h >= 1){
for(int i = h; i < arr.length; i++){
int temp = arr[i];
while (i >= h &&temp < arr[i-h]) {
arr[i] = arr[i-h];
i-=h;
}
arr[i] = temp;
}
h = h>>1;
}
}
优化
希尔排序的优化主要是针对增量序列的优化
(慕课的浙大数据结构)
上面这个例子做了很多次毫无意义的循环
所以有人就发现了,如果增量之间不互质的话,那有些情况就不管用了。
于是有些大佬们就整出了下面这些增量序列:Hibbard增量序列、Knuth增量序列、Sedgewick增量序列等等
当用这些序列作为增量的时候就可以改善这种情况,并且减少希尔算法一定的时间复杂度