原理:
又称为增量缩小排序。将待排序的数组按增量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) ;
}