对原始数组预处理,然后使用插入排序。
满足: 数组元素较少和 数组大部分元素有序俩个条件。
逐步折半增量
逐步分组进行粗调,再进行直接插入排序的思想,就是希尔排序。
分组跨度(4,2,1)
JAVA实现
//逐步折半+插入排序
public class MyShellSort {
public static void shellSort(int[] array){
int d = array.length;//希尔排序的增量
while (d>1){
d=d/2;
//x是在当前希尔增量下,数组被划分的组数
//对每一个组,进行插入排序
for (int x = 0;x<d;x++){
//原始有序区的下标是x,x+d是当前待插入值的下标
for (int i = x+d;i<array.length;i=i+d){
int temp = array[i];
int j;
//i-d是有序区最右边的值的下标
for (j=i-d;(j>=0)&&(array[j]>temp);j=j-d){
array[j+d] = array[j];//只覆盖,最后赋值
}
array[j+d] = temp;
}
}
}
}
测试方法:
public static void main(String[] args) {
int[] array = {5,8,6,3,9,2,1,7};
shellSort(array);
System.out.println(Arrays.toString(array));
}
逐步折半增量存在的问题:
对于这样的数组,希尔排序不但没有减少直接插入排序的工作量,反而白白增加了分组操作的成本。
原因:每一轮希尔增量之间是等比的,这就导致了希尔增量存在盲区。
Hibbard增量
增量序列:1,3,7,15…
通项公式:2k-1
使用这种增量的希尔排序,最坏的时间复杂度为:O(n3/2)
Sedgewick增量
增量序列:1,5,19,41…
通项公式:(9x4k)-(9x2k)+1
使用这种增量的希尔排序,最坏的时间复杂度为:O(n4/3)
总结
希尔排序是不稳定排序,值相同的元素有可能被调换位置。