希尔排序(Shell Sort)也称为递减增量排序,是插入排序的一种更高效的改进版本,希尔排序是不稳定的排序算法
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
- 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位
首先想一下希尔排序在编写代码的时候思路:我任务分为2步:
1、确定步长,对步长进行循环,通过步长找到所谓的虚拟数组。
2、把虚拟数组用直接插入排序就OK了。
昨天的时候想起了希尔排序就随手写了一个,在运行的时候发现了很多的错误。
public static int[] shellSort(int[] arr){
int n = arr.length;
int d=n;
while(true){
d = d/2;
for(int i=0; i<d; i++){
for(int j=i+d; j<n; j+=d){
int tmp = arr[j];
int k=j-d;
for( ; k>=0; k-=d){
if(tmp< arr[k]){
arr[k+d] = arr[k];
}
}
arr[k+d] = tmp;
}
}
if(d==1)
break;
}
return arr;
}
运行后会发现出错了,就以9, 8, 7, 6, 5, 4, 3, 2, 1, 0为例
当d=5的时候运行完是没有问题的结果变为4, 3, 2, 1, 0, 9, 8, 7, 6, 5
当d=2的时候此时虚拟数组是[4, 2, 0, 8, 6]和[3, 1, 9, 7, 5]最内层for循环对 4, 2, 0没问题变为0, 2, 4但是当读取到8的时候,此时的内循环无误,只是不进行交换,但是k却一直在减小,最后arr[k+d] = tmp的时候 k+d的值是0,把8赋给了数组第一个。导致出了问题,后来修改了一下。代码如下:
public static int[] shellSort(int[] arr){
int n = arr.length;
int d=n;
while(true){
d = d/2;
for(int i=0; i<d; i++){
for(int j=i+d; j<n; j+=d){
int tmp = arr[j];
int k=j-d;
for( ; k>=0&&tmp<arr[k]; k-=d){
arr[k+d] = arr[k];
}
arr[k+d] = tmp;
}
}
if(d==1)
break;
}
return arr;
}
运行就OK了。
在代码量没达到一定的水平的时候,不能仅仅感觉思想理解了就OK了,要自己去实现一下,还是有很多小细节问题需要注意。