align="center" marginwidth="0" marginheight="0" src="http://xviewee.googlepages.com/adsTop.html" frameborder="0" width="468" scrolling="no" height="60">
希尔(Shell)排序
相信大家如果学过数据结构与算法的话,一定对希尔排序有很深的印象吧,个人最喜欢的排序就是希尔排序了,希尔排序相对于其他算法的实现来说比较简单,而且效率也还可以,没有选择法、插入排序及冒泡排序的O(n
2)平方级时间复杂度,但当然也没有线性排序算法的O(n)级的线性时间复杂度,对于大型数据输入,线性算法肯定是最佳的选择,但对于中规模数据而言,希尔排序无疑是最佳的选择。算法大师Knuth在他的著作<<计算机程序设计艺术>>给出的希尔排序的平均时间复杂度为O(n
1.3),介于平方级和线性级之间。
如果你知道插入排序,就很容易理解其排序思想,他的做法是:先取一个整数d
1<n,把全部纪录分成d
1个组,所有距离为d
1倍数的记录放在一组中,先在各组内排序;然后取d
2<d
1重复上述分组和排序工作;直到d
i=1,即所有记录放在一组中为止。各组的排序可以采用直接插入法,也可以采用像直接选择排序或堆排序等其他排序方法。
直接插入排序在输入序列基本有序时,排序时间较少。另一方面,当n值较小时,n和n
2的差别也较小。Shell排序开始时增量较大,分组较多,每组的记录数目较少,故在各组内采用直接插入排序较快,后来增量d
i
‑逐渐缩小,分组数减少,各组的记录数增多,但由于已经按d
i-1分组排序,序列已经趋于有序态,所以一趟排序过程也较快。因此,Shell排序在效率上比直接排序有较大的改进。。
希尔排序的实现:
Void ShellSort(SortObject * pvector , int d)
{
int i,j,increment;
RecordNode temp;
for (increment = d ; increment > 0 ; increment /= 2)
{
for ( i = increment ; i < pvector->n; i ++ )
{
temp = pvector->record[i]; //保存待插入元素
j = i - increment;
while ( j >= 0 && temp.key < pvector->record[j].key)//对每组进行插入排序
{
pvector->record[j+increment] = pvector->record[j];
j -= increment;
}
if (j != i - increment) pvector->record[ j + increment ] = temp;
}
}
}
希尔排序示例:
初始序列:
49 , 38 , 65 , 97 , 13 , 76 , 27 , 49’
Increment=4:
①I = 4 , temp.key = 13 , j = 0,交换49和13:
13 , 38 , 65 , 97 , 49 , 76 , 27 , 49
’
②I = 5 , temp.key = 76 , j = 1,不交换38和76:
13 , 38 , 65 , 97 , 49 , 76 , 27 , 49
’
③ I = 6, temp.key = 27 , j = 2,交换65和27:
13 , 38 , 27 , 97 , 49 , 76 , 65, 49
’
④ I = 7, temp.key = 49 , j = 3,交换97和49
‘:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
Increment=2:
①I = 2 , temp.key = 27 , j = 0, 不交换13和27:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
②I =3 , temp.key = 49
’, j = 1,不交换38和49
’:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
③ I = 4, temp.key = 49 , j = 2,交换65和27:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
’
④ I =5, temp.key = 76 , j = 3,交换97和49
‘:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
⑤I = 6, temp.key = 65 , j = 2,交换65和27:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
’
⑥I = 7, temp.key = 97 , j = 3,交换97和49
‘:
13 , 38 , 65 ,49
’ , 49 , 76 , 27 , 97
Increment = 1:
同插入排序
最后得:
13
, 27 , 38 , 49’ , 49 , 65 , 76 , 97
如果仔细分析算法的每一步,我们可以看到对于增量划分的每一组数据,不是将分别对每一组数据进行插入排序,而是从各组交替进行插入排序的,从increment+1下标元素开始顺序遍历至最后一个元素,对每一个元素和他前面已成有序态的同一组数据进行插入排序。。