算法原理
希尔排序按其设计者希尔(Donald Shell)的名字命名,该算法由1959年公布。希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能,这样可以让一个元素可以一次性地朝最终位置前进一大步,然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序。步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
*插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
*但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位
算法思路:
1. 先取一个正整数 d1(d1 < n),把全部记录分成 d1 个组,所有距离为 d1 的倍数的记录看成一组,然后在各组内进行插入排序
2. 然后取 d2(d2 < d1)
3. 重复上述分组和排序操作;直到取 di = 1(i >= 1) 位置,即所有记录成为一个组,最后对这个组进行插入排序。一般选 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。
实例分析
假设有数组 array = [80, 93, 60, 12, 42, 30, 68, 85, 10],首先取 d1 = 4,将数组分为 4 组,如下图中相同颜色代表一组:
![](http://images2015.cnblogs.com/blog/1019477/201702/1019477-20170221223259132-1675867068.png)
然后分别对 4 个小组进行插入排序,排序后的结果为:
![](http://images2015.cnblogs.com/blog/1019477/201702/1019477-20170221223316804-10038238.png)
然后,取 d2 = 2,将原数组分为 2 小组,如下图:
![](http://images2015.cnblogs.com/blog/1019477/201702/1019477-20170221223328710-1734547308.png)
然后分别对 2 个小组进行插入排序,排序后的结果为:
![](http://images2015.cnblogs.com/blog/1019477/201702/1019477-20170221223340507-1221418793.png)
最后,取 d3 = 1,进行插入排序后得到最终结果:
![](http://images2015.cnblogs.com/blog/1019477/201702/1019477-20170221223348288-1186721309.png)
C语言实现
void shell_sort(ElementType A[],int N)
{
int i,j,Increment;
ElementType Tmp;
for(Increment = N / 2;Increment > 0; Increment /= 2)
for(i = Increment;i < N;i++)
{
Tmp = A[i];
for(j = i;j >= Increment;j -= Increment)
if(Tmp < A[j - Increment])
A[j] = A[J - Increment];
else
break;
A[j] = Tmp;
}
}