(二叉)堆数据结构是一种数组对象,它可以被视为一棵完全二叉树,树中每个结点与数组中存放该结点值的那个元素对应。树的每一层都是填满的,最后一层可能除外(最后一层从一个结点的左子树开始填)。数组A具有两个属性:A.length是数组中的元素个数,A.heapsize是存放在A中的堆的元素个数。树的根为A[1],由某个结点的下标i,可以简单地计算出其双亲结点及子结点:
Parent(i) {return (i / 2); }
LChild(i) {return (2 * i); }
RChild(i) {return (2 * i + 1); }
二叉堆有两种:最大堆和最小堆(小根堆)。在这两种堆中,结点内的数值都要满足堆特性,其细节则视堆的种类而定。在最大堆中,最大堆特性是指除了根以外的每个结点i,有
A[Parent(i)]>= A[i]
即某个结点的值至多是和其父结点的值一样大。这样,堆中的最大元素就存放在根结点中;并且,在以某一个结点为根的子树中,各结点的值都不大于该子树根结点的值。
最小堆的组织方式则刚好相反,最小堆特性是指除了根以外的每个结点i,有
A[Parent(i)]<= A[i]
最小堆的最小元素是在根部,最小堆通常在构造优先队列时使用。
堆结构上的一些基本操作的运行时间至多与树的高度成正比,为 O(lg(n))。以最大堆为例:
Max_Heapify()过程,其运行时间为O(lg(n)),用于保持最大(小)堆的性质
Build_MAX_Heap()过程,以线性时间运行,可以在无序的输入数组基础上构造出最大堆
HeapSort()过程,运行时间为 O(nlg(n)),对一个数组原地进行排序
O(lg(n))
Max_Heapify(A, i)
lc = LChild(i)
rc = RChild(i)
if (lc <= A.heapsize) and (A[lc]> A[i])
max =lc
else max = i
if (rc <= A.heapsize) and (A[rc]> A[max])
max =rc
if (max != i)
swap(A[i],A[max])
Max_Heapify(A, max) //对以关键结点为根的子树递归调用Max_Heapify
O(n)
Build_Max_Heap(A)
for i = (A.length/2) dowmto 1
Max_Heapify(A, i)
O(nlg(n))
HeapSort(A)
Build_Max_Heap(A)
for i = A.length downto 2
swap(A[1],a[i])
A.heapsize =A.heapsize - 1
Max_Heapify(A, 1)
O(1)
Heap_Maximum(A)
return A[1]
O(lg(n))
Heap_Extract_Max(A)
if (A.heapsize < 1)
error "heapunderflow"
max = A[1]
A[1] = A[A.heapsize]
A.heapsize = A.heapsize - 1
Max_Heapify(A, 1)
return max
O(lg(n))
Heap_Insert(A, key)
i = A.heapsize = A.heapsize + 1
A[i] = key
while (i > 1) and (A[Parent(i)]< A[i])
swap(A[i],A[Parent(i)])
i =Parent(i)