数据结构与算法——希尔排序学【学习笔记】
希尔排序
希尔排序因计算机科学家Donald L. Shell而得名,他在1959年发现了希尔抹序算法。希尔排序 基于插入排序,但是增 了一个新的特性,大大地提高了插入抹序的执行效率。
依靠这个特别的实现机制,希尔样序对于多达几千个数据项的,中等大小规模的数组排序表现 良好。希尔排序不像快速排序和其他时间复杂度为O(N*logN)的抹序算法那么快,因此对非常大的 文件排序,它不是最优选择。但是,希尔排序比选择排序和插入排序这种时间复杂度为0(N2)的排 序算法还是要快得多,并且它非常容易实现:希尔排序算法的代码既短又简单。它在最坏情况下的执行效率和在平均情况下的执行效率相比没有差很多。若在实际中证明它不够 快,再改換成诸如快速排序这样更高级的排序算法。
插入排序:复制的次数太多
希尔抹序是基于插入排序的。冋想一下 在插入排序执行的一半的时候,标记符左边这部分数据项都是排过序的(这些数据项之间是有序 的),而标记右边的数据项则没有排过序。这个算法取出标id符所指的数据项,把它存储在一个临 时变童里。接着,从刚刚被移除的数据项的左边第一个单元开始,每次把有序的数据项向右移动一个单元,直到存储在临时变量里的数据项能够有序回插
下面是插入排序带来的问题。假设一个很小的数据项在很靠近右端的位置上,这本来应该是值比较大的数据项所在的位胃,把这个小数据项移动到在左边的正确位置上,所有的中间数据项(这 个数据项原来所在的位罨和它应该移动到的位置之间的数据项)都必须向右移动一位。这个步骤对 每一个数据项都执行了将近N次的复制。虽然不是所有数据项都必须移动N个位置,但是数据项平 均移动了 N/2个位置,这就执行了 N次N/2个移位,总共是N2/2次复制。因此,插入排序的执行 效率是〇(N2)。
如果能以某种方式不必一个一个地移动所有中间的数据项,就能把较小的数据项移动到左边, 那么这个算法的执行效率就会有很大的改进。
n-增量排序
希尔排序通过加人插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而 使数据项能大跨度地移动。当这些数据项排过一趟序后,希尔排序算法减小数据项的间隔再进行排 序,依此进行下去。进行这些排序时数据项之间的间隔被称为增量,并且习惯上用字母h来表示, 图7.1显示了增量为4时对包含10个数据项的数组进行排序的第一个步骤的情况。在0、4和8号位置上的数据项己经有序了。
下图为完整的 以4为增量的排序
注意,在这个例子中,在完整以4为增童的希尔排序后,所有元素离它在最终有序序列中的位置相差都不到两个单元。这就是数组“基本有序”的含义,也正是希尔排序的奥秘所在。通过创建 这种交错的内部有序的数据项集合,把完成排序所必需的工作量降到了最小。
插入排序对基本有序的数组抻序是非常有效的。如果插入排序只需要把数据项移动一位或者两位,那么算法大概需要0(N)时间。这样,当数组完成4-增量排序之后,可以进行普通的插入排序,即1-增量排序,4-增量排序和1-增量排序结合起来应用,比前面不 执行4-增最排序而仅仅应用普通的插入排序要快得多。
减小间隔
上面已经演示了以4为初始间隔对包含10个数据项的数组进行棑序的情况。对于更大的数组, 开始的间隔也应该更大。然后间隔不断减小,直到间隔变成1。
举例来说,含有1000个数据项的数组可能先以364为增量,然后以121为增量,再以40为增量, 再以13为增量,再以4为增量,最后以1为增量进行希尔排序。用来形成间隔的数列(在本例中为364, 121,40, 13, 4. 1)被称为间隔序列。这里所表示的间隔序列由Knuth提出,此序列是很常用的。数列以逆向的形式从1开始,通过递归表达式 h = 3*h+1
代码如下: