是从插入排序来的,对于插入排序,当待排记录数很小时,直接插入排序的效率较高;当待排序列按关键字基本有序时直接插入的效率也较高
所以从这两点出发对直接插入排序进行了改进,便产生了希尔排序
该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
public static void main(String args[]){
int[] array={34,3,53,2,23,7,14,10};
shellsort(array);
for(int a:array)
System.out.print(a+" ");
}
private static void shellsort(int[] nums){
int len=nums.length;
if(len<2) return;
int gap=len/2;
while(gap!=0){
for(int i=0;i<gap;++i){
for(int j=i+gap;j<len;j+=gap){
if(nums[j]<nums[j-gap]){
int temp=nums[j];
int k=j-gap;
while(k>=0 && nums[k]>temp){
nums[k+gap]=nums[k];
k-=gap;
}
nums[k+gap]=temp;
}
}
}
gap/=2;
}
}
}
一个更好理解的希尔排序实现:将数组列在一个表中并对列排序(用插入排序)。重复这过程,不过每次用更长的列来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身仅仅对原数组进行排序(通过增加索引的步长,例如是用i += step_size
而不是i++
)。
例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10
然后我们对每列进行排序:
10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
將上述四行數字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:
10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
排序之后变为:
10 14 13 25 23 33 27 25 59 39 65 73 45 94 82 94
最后以1步长进行排序(此时就是简单的插入排序了)。
public class shellsort {
public static void main(String args[]){
int[] array={34,3,53,2,23,7,14,10};
shellsort(array);
for(int a:array)
System.out.print(a+" ");
}
private static void shellsort(int[] arr) {
int gap = 1, i, j, len = arr.length;
int temp;
while (gap < len / 2)
gap = gap * 2 + 1; // <O(n^(3/2)) by Knuth,1973>: 1, 4, 13, 40, 121, ...
for (; gap > 0; gap /= 2)
for (i = gap; i < len; i++) {
temp = arr[i];
for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
arr[j + gap] = arr[j];
arr[j + gap] = temp;
}
}
}