希尔排序算法
希尔排序(Shell Sort)是一种插入排序算法,因D.L.Shell于1959年提出而得名。又称作缩减增量排序。基本思考:希尔排序是优化的插入排序。基本的思想还是插入排序(插入置换,让子序列有序),它通过比较相距一定间隔的元素,所用的距离随算法进行而减少,直到相距为1为止。
①取数据的增量(希尔建议是hк=N/2和hк=hк+₁/2)
gap={5,2,1}
②在增量基础上,分独立的子数组
gap=5: {a[5] a[0]}, {a[6] a[1]}, {a[7] a[2]}, {a[8] a[3]} , {a[9] a[4]}
gap=2: {a[2] a[0]}
{a[4] a[2] a[0]}
{a[6] a[4] a[2] a[0]}……
……
{a[3] a[1]}
{a[5] a[3] a[1]}…….
gap=1: {a[1] a[0]}——类似直接插入排序
{a[2] a[1] a[0]}……
③在子数组内,执行插入排序
int[] data = { 9, 1, 2, 5, 7, 4, 8, 6, 3, 5 };
public static void shellSort(int[] d) {
int j;
//缩减距离:gap=hк/2 →5,2,1
for(int gap=d.length/2;gap>0;gap/=2) {
for(int i=gap;i<d.length;i++) {//增量插入排序
Integer tmp=d[i];
for(j=i;j>=gap&&tmp.compareTo(d[j-gap])<0;) {//j>=gap
d[j]=d[j-gap];//插入
j-=gap;//寻找下标j→tmp值,在同距离上的子数列上,合理的位置
//a[8]=5,在a[6],a[4],a[2],a[0],合理的位置是j=6;
}
System.out.println(gap+"=="+i+"=="+j);
d[j]=tmp;
}
}
//打印排序结果
for(int a:d) {
System.out.print(" "+a);
}
}
3.分析
希尔算法的分析是极其复杂的。平均运行时间O(N¹´³)。
当n较大时,那么希尔排序运行很快,大概在O(n¹´²⁵)。
思考:
基础:其算法的精髓在“缩减和增量”二字上。
开始时增量较大,分组较多,每组记录数目少,故每组内直接插入排序较快。
后来增量gap逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经在距离上排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
因此,希尔排序在效率上较直接插入排序有较大的改进。