希尔排序的思想是使数组中任意间隔为h的元素都是有序的,这样的数组被称为h有序数组,,换句话说一个h有序数组就是h个互相独立的的有序数组编制在一起组成的一个数组。
H=4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
A a a a
B b b b
C c c c
D d d d
如上有四个有序子数组a,b,c,d
实现希尔排序的一种方法是对于每个h,用插入排序将h个子数组独立的排序。
public class Shell
{
public static void sort(int[] a)
{
int n = a.length;
int h = 1;
while(h < n/3) //确定合适的间隔或者说子数组个数
h = 3*h + 1; //1,4,13,40,121,364,1093,....
while(h >= 1)
{
for(int i=h; i<n; i++)//从第一组之后第一个开始,相当于插入排序的i=1
{ //交替轮流处理不同的分组,每隔h次又处理到一个子数组
for(int j=i; j>=h && a[j]<a[j-h]; j-=h)
{
int t = a[j];
a[j] = a[j-h];
a[j-h] = t;
}
}//这一个间隔h下的所有子数组已经排好序
h = h/3;//缩小间隔h继续排序,直到1
}
}
public static void main(String[] args)
{
int[] arr = {3,4,5,8,7,6,9,0,1,2};
Shell.sort(arr);
for(int i=0; i<10 ; i++)
{
System.out.println(arr[i]);
}
}
}
小结:
1. 其实在理解了插入排序之后,希尔排序还是很简单的,当然这个分组的方式不是固定的,缩小分组也不一定是除以三。也有一种比较省力的做法是直接n/2来分组,每次再除以二,直到h=1,也就是插入排序。对于理解上面代码的h,能对数论中的同余有一定的理解最好不过了。
2. 希尔排序是三重循环,最外层是拿来控制分组的,并不断缩小分组,内层两重循环就是插入排序,把 1 换成 h 来理解即可。