算法原理:
希尔排序实际上是一种插入排序算法。取一个小于n的整数d1作为第一个增量,把数组分成d1个组。所有距离为d1的倍数的元素放在同一个组中。在各组内进行插入排序。然后取第二个增量d2<d1,重复第一次的分组和排序过程,直到所取的增量dt=1,即所有记录放在统一族中进行插入排序。
以上图的过程为例说明希尔排序的过程:
d1=5 分组结果为 (a1, a6, a11), (a2, a7, a12), (a3, a8), (a4, a9), (a5, a10) 对每一组元素进行插入排序得到第二行的结果
d2=3 分组结果为 (a1, a4, a7, a10), (a2, a5, a8, a11), (a3, a6, a9, a12) 对每一组元素进行插入排序得到第三行的结果
d3=1 分组结果为 (a1, a2, ..., a12) 进行插入排序,得到排好序的数组
d的取值:
一般情况下,第一次取n/2, 第二次取n/4,第三次取n/8...
算法性能分析:
时间复杂度分析:希尔排序的时间复杂度和增量的选择有关。一般情况下,最坏时间复杂度为O(N^2),最好的时间复杂度为O(N^1.3),平均时间复杂度为O(nlogn) - O(n^2)。
空间复杂度分析:O(1)
稳定性:不稳定
总结:
1. 不需要大量的辅助空间,实现简单,代码短。
2. 希尔排序在最坏的情况下和平均情况下执行效率相差不多,而快速排序在最坏的情况下效率非常差。
3. 几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快, 再改成快速排序这样更高级的排序算法
Java版本实现:
private void shellsort(int[] A)
{
for(int d=A.length/2;d>0;d=d/2)
{
for(int i=d;i<A.length;i++)
{
int j=i-d;
int key = A[i];
while(j>=0 && A[j] > key)
{
A[j+d] = A[j];
j -= d;
}
A[j+d] = key;
}
}
}