原理:
将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,待整个待排序序列 “基本有序”后,最后再对所有元素进行一次直接插入排序
实例:
给定一组步长为 { n/2, n/2/2, ... ,1}
初始的数组是 { 5,4,9,8,7,6,0,1,3,2} , h是数组的长度10
h = h/2 = 5, 因此分为5组, {5,6} {4,0} {9,1} {8,3} {7,2} ,分别对这5个子序列排序,结果为 {5,0,1,3,2,6,4,9,8,7}
h = h/2 = 2, 数组分为2组, { 5,1,2,4,8} { 0,3,6,9,7},分别对这两组排序,结果为 {1,0,2,3,4,6,5,7,8,9}
h = h/2 = 1, 只有一个组,这时对整个组排序,结果为 {0,1,2,3,4,5,6,7,8,9}
i 表示正在比较的元素所在的位置,从 h/2 开始,j 刚开始的值是在i的位置,即就是 j=i-h , j表示和i在一组的位于i元素位置之前的元素,所以j的移动为 j-h, 就是 j = j-h ,并且 j>=0
代码:
private void shellSort(int[] a) {
int length = a.length;
int i,j,h,temp;
// 步长序列为 {h/2, h/2/2, ..., 1}
for(h=length/2; h>0; h=h/2){
// i从h开始
for(i=h; i<length; i++){
temp = a[i];
// j从i-h开始,i-h是同一组序列之间的距离
for(j=i-h; j>=0; j-=h){
if(temp < a[j]){
a[i] = a[j];
a[j] = temp;
}else
break;
}
}
}//for
}//
使用Junit测试:
@Test
public void main(){
// int[] a = {26,53,67,48,57,13,48,32,60,50};
int[] a = {5,4,9,8,7,6,0,1,3,2};
shellSort(a);
for(int i:a){
System.err.print(i+" ");
}
}