shell排序就是插入排序的一个变化形式,由于插入排序是每一个元素都会进行比较,并拿当前元素和之前的所有元素进行比较,在最坏情况下。因此,DL.Shell于1959年提出了shell排序,也就是分组插入排序,将一个待排序数组进行分组,在多个组之间的对应元素进行插入排序,通过不断的增加组值,来使待排序数组完成一次排序。因此shell排序也叫做增量插入排序。本人心里面思考了这个排序,整整想了2天。因此记录下这个过程了。
假如现在有待排序数组:10,14 ,73 ,25 ,23 ,13 ,27 ,94, 33, 39 ,25 ,59, 94, 65, 82, 45。n=16;
1 那么我们可以定一个分组gap,gap = n/2。那么这个数组就分成两组了。
10,14 ,73 ,25 ,23 ,13 ,27 ,94,
33, 39 ,25 ,59, 94, 65, 82, 45
这样的话,10和33做比较,14和39做比较,73和25做比较。25和59做比较。。。。后面的依次比较。当gap = 8时,排序的结果是:
10 14 25 25 23 13 27 45
33 39 73 59 94 65 82 94
2 现在在增加gap,gap = n/4 = 4。那么这个数组就分成四组了。
10 14 25 25
23 13 27 45
33 39 73 59
94 65 82 94
这次比较就是10,23,33,94做比较,14,13,39,65做比较。25,27,73,82做比较,25,45,59,94做比较。此时,排序的结果是:
10 13 25 25
23 14 27 45
33 39 73 59
94 65 82 94
3 现在在增加gap,gap = n/8=2。那么这个数组就分成8组,进行排序,最后一直到gap=1,也就是普通的插入排序了。
有了以上的过程,我们代码就比较容易写出来了。
1 首先是定义gap值,然后每次减少gap的值,来增加分组数量。for(int gap=n/2;gap>0;gap/=2)
2 然后针对每个分组对应的值,进行比较,插入排序。我们默认从第一个gap开始选中元素,一直到数组最后一个元素,我们通过当前选中元素的索引加减gap值,来实现对每一组元素进行比较。
for(int i=gap;i<n;i++){
for(int j=i-gap;j>=0&&a[j]>a[i+gap];j-=gap)
swap(a,j,j+gap);
}
我们来看看完整的代码吧。
package com.bplead.sort;
public class ShellSort {
public static void main(String[] args) {
int a[] = {10,14 ,73 ,25 ,23 ,13 ,27 ,94, 33, 39 ,25 ,59, 94, 65, 82, 45};
int size = a.length;
int temp = 0;
for(int gap = size/2;gap>0;gap/=2){
for(int i=gap;i<size;i++){
for(int j=i-gap;j>=0&&a[j]>a[j+gap];j-=gap){
temp = a[j];
a[j] = a[j+gap];
a[j+gap] = temp;
}
}
print(a);
}
print(a);
}
private static void print(int a[]){
for(int i=0;i<a.length;i++)
System.out.print(a[i] +" ");
System.out.println();
}
}
运算结果就和我们之前分析的一样,如下:
10 14 25 25 23 13 27 45 33 39 73 59 94 65 82 94
10 13 25 25 23 14 27 45 33 39 73 59 94 65 82 94
10 13 23 14 25 25 27 39 33 45 73 59 82 65 94 94
10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94
10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94