希尔排序是插入排序的优化算法,时间复杂度为O(nlogn),也称为增量缩小的算法.
希尔排序使用了一个序列h1,h2,h3...hk,称为增量序列,只要h1=1 任何增量序列都是可行的,不过有些增量序列可能会比另外一些增量序列更好一点.
在使用增量hk排序以后,对每个i,都有a[i]<=a[i+k],即相隔k个的元素都已经排序,此时称文件是hk排序的.
对希尔排序来说一个重要的性质就是,一个hk排序的文件,保持他的hk有序性,即使用下一个增量(hk-1)排序后,之前基于hk的排序依然是有效的.
举例说明
数组a = [4,2,1,9,3,5,8,6,7]
通常我们选取的增量序列是 hk= length/2(向下取整) hk-1 = hk/2(向下取整) ... h1 =1(更好的增量序列,暂时不讨论)
那么对a来说我们选取的增量序列就是 4,2,1
原数组a = [4,2,1,9,3,5,8,6,7]
第一轮,增量序列为4
a[4]=3,a[0]=4,{4,3}3插入排序(改变)
a=[3,2,1,9,4,5,8,6,7]
a[5]=5,a[1]=2,{2,5}5插入排序(不变)
a=[3,2,1,9,4,5,8,6,7]
a[6]=8,a[2]=1,{1,8}8插入排序(不变)
a=[3,2,1,9,4,5,8,6,7]
a[7]=6,a[3]=9,{9,6}6插入排序(改变)
a=[3,2,1,6,4,5,8,9,7]
a[8]=7,a[4]=4,{4,7}7插入排序(不变)
a=[3,2,1,6,4,5,8,9,7]
第一轮结束.a=[3,2,1,6,4,5,8,9,7]
第二轮排序,增量序列为2
a[2]=1,a[0]=3,{3,1}1插入排序(改变)
a=[1,2,3,6,4,5,8,9,7]
a[3]=6,a[1]=2,{2,6}6插入排序(不变)
a=[1,2,3,6,4,5,8,9,7]
a[4]=4,a[2]=3,a[0]=1,{1,3,4}4插入排序(不变)
a=[1,2,3,6,4,5,8,9,7]
a[5]=5,a[3]=6,a[1]=2,{2,6,5}5插入排序(改变)
a=[1,2,3,5,4,6,8,9,7]
a[6]=8,a[4]=4,a[2]=3,a[0]=1,{1,3,4,8}8插入排序(不变)
a=[1,2,3,5,4,6,8,9,7]
a[7]=9,a[5]=6,a[3]=5,a[1]=2,{2,5,6,9}9插入排序(不变)
a=[1,2,3,5,4,6,8,9,7]
a[8]=7,a[6]=8,a[4]=4,a[2]=3,a[0]=1,{1,3,4,8,7}7插入排序(改变)
a=[1,2,3,5,4,6,7,9,8]
第二轮排序结束.a=[1,2,3,5,4,6,7,9,8]
第三轮排序开始,增量为1
a[1]=2,a[0]=1,{1,2}2插入排序(不变)
a=[1,2,3,5,4,6,7,9,8]
a[2]=3,a[1]=2,a[0]=1,{1,2,3}3插入排序(不变)
a=[1,2,3,5,4,6,7,9,8]
a[3]=5,a[2]=3,a[1]=2,a[0]=1,{1,2,3,5}5插入排序(不变)
a=[1,2,3,5,4,6,7,9,8]
a[4]=4,a[3]=5,a[2]=3,a[1]=2,a[0]=1,{1,2,3,5,4}4插入排序(改变)
a=[1,2,3,4,5,6,7,9,8]
a[5]=6,a[4]=5,a[3]=4,a[2]=3,a[1]=2,a[0]=1,{1,2,3,4,5,6}6插入排序(不变)
a=[1,2,3,4,5,6,7,9,8]
a[6]=7,a[5]=6,a[4]=5,a[3]=4,a[2]=3,a[1]=2,a[0]=1,{1,2,3,4,5,6,7}7插入排序(不变)
a=[1,2,3,4,5,6,7,9,8]
a[7]=9,a[6]=7,a[5]=6,a[4]=5,a[3]=4,a[2]=3,a[1]=2,a[0]=1,{1,2,3,4,5,6,7,9}9插入排序(不变)
a=[1,2,3,4,5,6,7,9,8]
a[8]=8,a[7]=9,a[6]=7,a[5]=6,a[4]=5,a[3]=4,a[2]=3,a[1]=2,a[0]=1,{1,2,3,4,5,6,7,9,8}8插入排序(改变)
a=[1,2,3,4,5,6,7,8,9]
第三轮排序完毕,整体排序完毕
数组a=[1,2,3,4,5,6,7,8,9]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public static <T extends Comparable<? super T>> void shell(T[] arr) { 2 int length = arr.length; 3 for (int step = length / 2; step > 0; step /= 2) { 4 for (int i = step; i < length; i++) { 5 int j = 0; 6 T tmp = arr[i]; 7 for (j = i; j >= step && tmp.compareTo(arr[j - step]) < 0; j -= step) { 8 arr[j] = arr[j - step]; 9 } 10 arr[j] = tmp; 11 } 12 13 } 14 }