四、【排序】堆排序(heapsort)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18108083/article/details/85208338

借助堆数据结构的相关算法实现高效的排序,称为堆排序(heapsort)。因为由堆构成的优先级队列可以支持在整个堆中取出优先级最高的元素,而且其操作算法非常高效,利用这个getMax()操作,可以很方便地实现排序操作。本文介绍基于完全二叉堆的堆排序算法。(完全二叉堆的介绍其实现可参考之前的博客https://blog.csdn.net/qq_18108083/article/details/85203134

一、原理:

算法的总体思路和策略与选择排序算法基本相同:将所有词条分成未排序和已排序两类,不断从前一类中取出最大词条插入到后一类中,算法启动之初,所有词条均属于前一类,后一类不断增长,当所有词条都已转入后一类时,即完成排序。

二、具体过程 

这里的待排序词条既然已组织为向量(完全二叉堆),不妨将其划分为前缀H和与之互补的后缀S,分别对应于上述未排序和已排序部分。与常规选择排序算法一样,在算法启动之初H覆盖所有词条,而S为空。新算法的不同之处在于,整个排序过程中,无论H包含多少词条,始终都组织为一个堆。另外,整个算法过程始终满足如下不变性:H中的最大词条不会大于S中的最小词条,除非二者之一为空,比如算法的初始和终止时刻。

 算法的迭代过程如上图所示,首先如图(a),取出首单元词条m,将其与末词条x进行交换,m既是当前堆中的最大者m,同时根据不变性也不大于S中的任何词条,故如此交换之后M必处于正确的排序位置,故如图(b),此时可等效地认为S向前扩大了一个单元, H相应地缩小了一个单元。请注意,如此重新分界之后,H和S依然满足以上不变性。至此,唯一尚未解决的问题是,词条X通常不能“胜任”堆顶的角色,不满足完全二叉堆的堆序性,所以需要进行下滤操作。

可见,整个堆排序过程就是迭代地删除完全二叉堆的堆顶,末词条转移到堆顶维持完全二叉堆的结构性,然后从新堆顶词条开始进行下滤,以维持完全二叉堆的堆序性,这样删除直到堆空,排序结束。

三、性能分析

(a) 时间复杂度:

在每一步选代中,交换M和X只需常数时间,对X的下滤调整不超过O(logn)时间。因此,,全部迭代n步累计耗时不超过O(nlogn),即便使用蛮力算法而不是Floyd算法来完成H初始化,整个算法的运行时间也不超过O(nlogn)

(b) 空间复杂度:

纵览算法的整个过程,除了用于支持词条交换的1个辅助单元,几乎不需要更多的辅助空间,堆排序属于就地算法

总结:得益于问量结构的简洁性,几乎所有以上操作都可便捷地实现,因此该算法不仅可简明地编码,其实际运行效率也因此往往要高于其它O(nlogn)的算法。高运行效率、低开发成本以及低源消耗等诸多优点的完美结合,若离开堆这一精巧的数据结构实在难以想象。

猜你喜欢

转载自blog.csdn.net/qq_18108083/article/details/85208338