`
gaofen100
  • 浏览: 1191526 次
文章分类
社区版块
存档分类
最新评论

堆排序

 
阅读更多

顾名思义,堆排序算法使用堆来排序无序的anarray数组。首先,算法将数组转换为堆。为完成转换,一种方法是使用heapInsert函数,将项逐一入堆。
还有一种方法有数组anArray的项构建堆,这种方法的效率更高。假设anArray的原始内容如图1-a所示。将数组anArray的项指派给树的节点,从根开始,从左到右,逐渐下移将数组视为二叉树。结果如图1-b所示。此后,反复调用heapRebuilt,将该树转换为堆。heapRebuilt将半堆转换为堆。半堆的子树为堆,但根为就位。但是,树中有供heapRebuilt处理的半堆吗?图1-b的树不是半堆,但查看叶子,可以找到半堆;换言之,每个叶子是一个半堆。首先从左到右在叶子上调用heapRebuilt,接着沿树上移,在到达节点s时,其子树为堆。于是,heapRebuilt将以s为根的半堆转换为堆。


图1 (a)anArray的原始内容 ;(b)anArray的相应二叉树
下面的算法将包含n个项的anArray数组转换为堆,这是堆排序算法的第一个步骤。


实际上,在前面的for语句中,可用n/2替换n-1。(因为从n/2到n-1的节点都为叶子,已经是堆了,没有必要在调用heapRebuilt函数)。图2跟踪图1-a的数组的算法。

图2 将anArray数组转换为堆
将数组转换为堆之后,堆排序将数组分为两个区域:heap(堆)和Sorted(有序),如图3所示,Heap区域在anArray[0..last],Sorted区域anArray[last..n-1]。开始时,Heap区域包含anArray的所有内容,而sorted区域为空,换言之,last=n-1。


图3 堆排序将数组分成两个区域
在算法的每一步,将项I从heap区域移到Sorted区域。堆排序算法的不变式为:
* 在步骤K后,Sorted区域包含anArray的K个最大值,且有序,换言之,anArray[n-1]是最大值,anArray[n-2]是第二最大值,以此类推。
* Heap区域中的项构成堆。
只要保持不变式,I必然是Heap区域中的最大项,故必为堆的根。为完成移动,交换堆的根项与堆的最后一项,换言之,交换anArray[0]与anArray[last],然后last的值减1。结果,移动后,将Heap区域转换为堆,因为新项可能位置不对。可用heapRebuilt下移根项,是Heap区域再一次构成堆。
下面的伪码总结这些步骤:

堆排序的效率分析与归并相似,在最坏的情况及平均情况下,两种算法均为O(n*log n)。与归并排序相比,堆排序的优势在于不需要第二个数组。快速排序在平均情况下也O(n*log n),但在最坏的情况下为O(n^2)。尽管在最坏的情况下的效率不高,快速排序任然为首选的排序方法。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics