算法思想:
①先将待排序记录序列分割成若干个“较稀疏的”子序列,分别进行直接插入排序。
②经过上述粗略调整,整个序列的记录已基本有序,最后再对全部序列进行一次直接插入排序。
分析:
希尔排序的特点是,子序列的构成不是简单的逐段分割,而是将某个相隔某个增量的记录组成一个子序列。如上面的例子,第一堂排序时的增量为5,第二趟排序的增量为3。由于前两趟的插入排序中记录的关键字是和同一子序列中的前一个记录的关键字进行比较,因此关键字较小的记录就不是一步一步地向前挪动,而是跳跃式地往前移,从而使得进行最后一趟排序时,整个序列已经做到基本有序,只要作记录的少量比较和移动即可。因此希尔排序的效率要比直接插入排序高。
希尔排序的分析是复杂的,时间复杂度是所取增量的函数,这涉及一些数学上的难题。但是在大量实验的基础上推出当n在某个范围内时,时间复杂度可以达到O(n^1.3)。
具体实现:
首先选定两个记录间的距离d1,在整个待排序记录序列中将所有间隔为d1的记录分为一组,进行组内直接插入排序,然后再取两个记录间的距离d2<d1,在整个待排序序列中,将所有间隔为d2的记录分为一组,进行组内直接插入排序,直至选定两个记录间的距离dt=1为止,此时只有一个序列,即整个待排序记录序列。(一般情况下d1=n/2,di+1=di/2(向下取整),并且最后一个增量等于1)
package com.haobi;
/*
* 希尔排序
*/
public class ShellSort {
public static void shellSort(int[] array) {
int length = array.length;//数组长度
int j;
int d;//定义记录间的距离d
int temp;
for(d=length/2;d>0;d=d/2) {//不断缩小两个记录间的距离d,直至d=1
for(int i=d;i<length;i++) {
temp = array[i];//存放待插入数据
for(j=i-d;j>=0;j-=d) {//以间隔d遍历整个数组,进行组内直接插入排序
if(temp<array[j]) {
array[j+d] = array[j];//从子集中进行数据交换并寻找插入位置
}else {
break;
}
}
array[j+d] = temp;//将待插入的数据插入
}
}
}
public static void main(String[] args) {
int[] array = {16,25,12,30,47,11,23,36,9,18,31};
shellSort(array);
for(int i=0;i<array.length;i++) {
System.out.print(array[i]+" ");
}
}
}
程序输出结果如下:
9 11 12 16 18 23 25 30 31 36 47