上篇博客 写了一点关于插入排序和选择排序的东西,今天以我的理解来介绍一下Shell排序
我们知道 插入排序在数组基本有序的条件下,性能表现的很好。
基于这点,我们想能不能让数组在插入排序之前变得基本有序,当然,这点是可以做到的。
我们在shell排序中通过将数组分组比如 1,3,4,6,2,5 这六个元素我们分为2组的话 就有a[0],a[2],a[4]={1,4,2} a[1],a[3],a[5]={3,6,5}
我们将这两组分别排序就有了1,3,2,5,4,6 这样一来数组就变得局部有序 分组长度我们称为增量h 我们按上述步骤逐渐将增量变小
直到h=1 就成了插入排序
下面我们介绍步骤
首先我们确定增量h
int N = a.length
while(h<N/3) h=3*h+1; //1,4,13,40.....
当然确定增量有不同的方法
然后对应每个增量 我们都进行一次插入排序
while(h>=1){
for(int i=h;i<a.length;i++) {
for(int j=h;j>=h&&less(a[j],a[j-h]);j-=h)
exch(a,j,j-h);
}
h = h/3;
} //把a[i[插入到a[i-h],a[i-2*h]......
具体代码:
public class ShellSort { public static void show(Comparable [] a){ for(int i=0;i<a.length;i++) System.out.printf("%f ",a[i]); System.out.println(); } public static boolean less(Comparable a,Comparable b){ return a.compareTo(b)<0; } public static void exch(Comparable [] a,int i,int j){ Comparable temp = a[i]; a[i] = a[j]; a[j] = temp; } public static void ShellSort(Comparable [] a){ int h =1; int t=0; while(h < a.length/3) h = 3*h+1; //控制增量h while(h>=1){ for(int i=h;i<a.length;i++){ for(int j=i;j>=h&&less(a[j],a[j-h]);j-=h) exch(a,j,j-h); } h=h/3; t++; System.out.printf("第%d次排序后: ",t); show(a); } } public static void main(String [] args){ Double [] t = new Double [16]; for(int i=0;i<t.length;i++){ t[i] = Math.random()*15; } System.out.println("未排序时"); show(t); ShellSort(t); } }
先溜了。。。