We have defined the following functions for priority queue:
empty : T
singleton : S -> T
findMin : T -> (S union {T})
insert : T x S -> T
deleteMin : T -> T x (S union {T})
meld : T x T -> T
fromSeq : S seq -> T
where meld
merge two priority queues.
Priority can be used for sequential \log n heap sort. And other problems: - Huffman codes - clustering algorithms - event simulation - kinetic algorithms for motion simulation - you can use a max and a min heap for building "medium queue" (with quick select)
Linked List: ether the following
deleteMin
O(1), insert
\Omega(n)
deleteMin
\Omega(n), insert
O(1)
Balanced Tree: deleteMin
(delete left-most), insert
both O(\log n). meld
O(n).
Heaps: unlike search tree, heap only maintain partial order (min heap small on root, max heap big on root)
leftist heaps
binomial heaps
pairing heaps
Fibonacci heaps
Binary Heap:
shape property: all levels have 2 leafs except for last level
heap property: parents are bigger/smaller than children
Calculation: heap can be implemented using sequence
left i = 2i + 1
right i = 2i + 2
parent i = ceil(i/2)-1
Implementation
Bound: same as balanced BST but faster in practice when maximum size is known (otherwise need dynamically sized array)
Note that Leftist Heap is better than all heaps listed here.
Leftist Heap: does not maintain BST property
meld
: basic operation of all other operations
deleteMin
: delete root and meld
two subtree
insert
: meld
with singleton
fromSeq
: fromSeq S = Seq.reduce Q.meld Q.empty (Seq.map Q.singleton S)
(O(n) work O(\log^2 n) span)
Naive Meld: when meld two trees, choose choose right spine of smaller tree to insert bigger tree. (assuming min-heap, smaller tree is a tree with smaller key on root) O(m+n) work since resulting tree is imbalanced.
Leftist Meld: add another field called rank
on each node, denoting the number of nodes you would traverse to reach the end if you always go right.
formal construction: rank(Leaf) = 0, rank(node(\_, \_, R)) = 1 + rank(R)
leftist property: for every node x in the heap, rank(L(x)) \geq rank(R(x)). Note that this may still cause tree to be unbalanced toward the left. But this is fine since we always meld-insert on the right.
Complete heap always Leftist.
makeLeftistNode()
piles larger right-rank tree on the left
Leftist Rank Lemma: rank of the root node is at most \log_2 (n+1).
To prove this. notice the smallest (in terms of the number of nodes) rank-0 heap has 0 node, and rank-1 heap has 1 node, rank-2 heap has 1 + 1 + 1 = 3 nodes (by the leftist property, the rank of the left child of x must be at least the rank of the right child of x), rank-3 heap has 1 + 3 + 3 nodes. In general, let n(r) denotes the number of nodes of a smallest heap with rank r, then if x is the root of smallest heap with rank r: n(r) = 1 + n(rank(L(x))) + n(rank(R(x))). Solving the recurrence gives smallest heap with rank r must contain at least 2^r - 1 nodes.
Leftist Work: makeLeftistNode()
guarantees leftist property. Since meld
only traverse right spines of A, B and both trees are leftist, we have W = O(\log m = \log n).
Table of Content