原理:
又稱爲增量縮小排序。將待排序的數組按增量n劃分成n組(把它們當成一組,但不實際分組,只是當成一組來看,只是爲了說明分組關係),每組元素的下標相隔n,使用插入排序法對每一小組進行排序,然後縮小增量n,重新劃分小組進行排序,直到n爲1時對整個數組進行插入排序,排序過程結束。
要點:
1.增量的選擇,一般會選擇array.length / 2作爲初始增量,之後n/=2 ;
2.增量n=1時對整個數組進行插入排序結束。
講解:
設數組爲array[0...len-1],數組長度爲len
1. 初始時,增量n=len/2;
2. 將數組劃分成n組,如array1[0,n,2n]、array2[1,n+1,2n+1]、array3[2,n+2,2n+2]...arrayn[n-1,n+n-1,2n+n-1];
3. 對每個小組進行插入排序,n=n/2;
4.重複第2步,直到n=1時排序結束;
實例:
現有數組[6, 2, 1, 7, 9, 4, 3, 8, 5, 10],要求對其進行升序排序。
①初始時:n=len/2=5 ;
②根據增量對該數組進行分組得:[6,4],[2,3],[1,8],[7,5],[9,10],如圖1.1;
③對每個小組進行插入排序得:[4,2,1,5,9,6,3,8,7,10],如圖1.2
④增量n=n/2=2,對數組繼續進行分組得:[4,1,9,3,7],[2,5,6,8,10],如圖1.3;
⑤對每個小組進行插入排序得:[1,2,3,5,4,6,7,8,9,10],如圖1.4;
⑥增量n=n/2=1,對數組進行分組,即還是原來的數組:[1,2,3,5,4,6,7,8,9,10],如圖1.5;
⑦對分組進行插入排序得:[1,2,3,4,5,6,7,8,9,10],如圖1.6;
⑧增量n=1,排序結束。
程序:
/**
* 希爾排序法(基於插入排序)
* @param array
*/
public static void shellSort(int[] array){
int gap ; //增量
int i,j,tmp ;
for(gap=array.length/2;gap>0;gap/=2){
for(i=gap;i<array.length;i++){
tmp = array[i] ;
for(j=i;j>=gap;j-=gap){ //基於快速排序
if(array[j-gap]>array[j]){//當array[high] < array[high+gap],前面的值都比array[high+gap]小,不需再執行內循環,還可以優化
tmp = array[j] ;
array[j] = array[j-gap] ;
array[j-gap] = tmp ;
}
}
}
}
}
/**
* 希爾排序法優化(基於插入排序)
* @param array
*/
public static void shellSort2(int[] array){
int gap ; //增量
int i,j,tmp ;
for(gap=array.length/2;gap>0;gap/=2){
for(i=gap;i<array.length;i++){
tmp = array[i] ;
for(j=i;j>=gap&&array[j-gap]>tmp;j-=gap){
array[j] = array[j-gap] ;//大的值往後移
}
array[j] = tmp ;
}
}
print(array) ;
}