堆排序的性质:
堆排序的时间复杂度是O(n lgn)。
堆排序具有空间原址性:任何时候都只需要常数个额外的元素空问存储临时数据。
堆排序引人了另一种算法设计技巧:使用一种我们称为“堆”的数据结构来进行信息管理。
堆不仅用在堆排序中,而且它也可以构造一种有效的优先队列。
堆的分类以及其分类特性:
二叉堆可以分为两种形式:最大堆和最小堆。在这两种堆中,结点的值都要满足堆的性质,但一些细节定义则有所差异。
在最大堆中,最大堆性质是指除了根以外的所有结点i都要满足:A[PARENT(i) ]>=A[i]
也就是说:某个结点的值至多与其父结点一样大。因此.堆中的最大元素存放在根结点中;并且.在任一子树中,该子树所包含的所有结点的值都不大于该子树根结点的值。
最小堆的组织方式正好相反:最小堆性质是指除了根以外的所有结点i都有A[PARENT(i) ]<=A[i]
在堆排序算法中,我们使用的是最大堆。最小堆通常用于构造优先队列。
相关操作
维护堆的性质
MAX-HEAPIFY是用于维护最大堆性质的重要过程。它的输入为一个数组A和一个下标i,
在调用MAX-HEAPIFY的时候,我们假定根结点为LEFT(i)和RIGHT(i)的二叉树都是最大堆,但这时A[i]有可能小于其孩子,这样就违背了最大堆的性质。MAX-HEAPIFY通过让A[i]的值在最大堆中“逐级下降”.从而使得以下标‘为根结点的子树重新遵循最大堆的性质。
伪代码示例:
MAX-HEAPIFY (A, i )
l= LEFT (i)
r= RIGHT (i)
If l<=A. heap-size and A[l]>A[i]
largest = l
else largest = i
if r <= A.heap-size and A[r] > A[largest]
largest = r
if largest != i
exchange A[i] with A[largest]
MAX-HEAPIFY (A, largest )
示例图:
建立堆
用自底向上的方法利用过程MAX- HEAPIFY把一个大小为n=A. length的数组换为最大堆。过程BUILD-MAX-HEAP对树中的其他结点都调用一次。
伪代码示例
BUILD-MAX-HEAP(A)
A.heap-size = A.length
for i = [A.length/2] downto 1//这里从length/2开始是因为子数组A(n/2+1.. n)中的元素都是树的叶结点。每个叶结点都可以看成只包含一个元素的堆,叶子节点没有必要维护堆的性质。
MAX-HEAPIFY (A, i )
示例图:
堆排序算法
初始时候.堆排序算法利用BUILD-MAX-HEAP将数组A[1…n]建成最大堆,其中n=A. length。因为数组中的最大元素总在根结点A[1]中.通过把它与A[n]进行互换,我们可以让该元素放到正确的位置。这时候,如果从堆中去掉结点n(这一操作可以通过减少A. leapsize的值来实现),利余的结点中,原来根的孩子结点仍然是最大堆,而新的根节点可能会违背最大堆的性质。调用MAX-HEAPIFY (A. 1)来维护最大堆的性质,从而在
A[l…,n-1]上构造一个新的最大堆.堆排序算法会不断重复这一过程,直到堆的大小从n-1下降到2。
伪代码示例:
HEAPSORT(A)
for i = A.length downto 2
exchange A[1] with A[i] //新的根节点(即交换之前数组最后一位元素)可能会违背最大堆的性质
A.heap-size -= 1 //从堆中去掉结点
MAX-HEAPIFY (A, 1 ) //维护最大堆的性质
示例图: