6.5 Priority queues
6.51
Illustrate the operation $\text{HEAPEXTRACTMAX}$ on the heap $A = \langle 15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1 \rangle$.

Original heap.

Extract the max node $15$, then move $1$ to the top of the heap.

Since $13 > 9 > 1$, swap $1$ and $13$.

Since $12 > 5 > 1$, swap $1$ and $12$.

Since $6 > 2 > 1$, swap $1$ and $6$.
6.52
Illustrate the operation of $\text{MAXHEAPINSERT}(A, 10)$ on the heap $A = \langle 15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1 \rangle$.

Original heap.

Since $\text{MAXHEAPINSERT}(A, 10)$ is called, we append a node assigned value $\infty$.

Update the $key$ value of the new node.

Since the parent $key$ is smaller than $10$, the nodes are swapped.

Since the parent $key$ is smaller than $10$, the nodes are swapped.
6.53
Write pseudocode for the procedures $\text{HEAPMINIMUM}$, $\text{HEAPEXTRACTMIN}$, $\text{HEAPDECREASEKEY}$, and $\text{MINHEAPINSERT}$ that implement a minpriority queue with a minheap.
HEAPMINIMUM(A)
return A[1]
HEAPEXTRACTMIN(A)
if A.heapsize < 1
error "heap underflow"
min = A[1]
A[1] = A[A.heapsize]
A.heapsize = A.heapsize  1
MINHEAPIFY(A, 1)
return min
HEAPDECREASEKEY(A, i, key)
if key > A[i]
error "new key is larger than current key"
A[i] = key
while i > 1 and A[PAREANT(i)] > A[i]
exchange A[i] with A[PARENT(i)]
i = PARENT(i)
MINHEAPINSERT(A, key)
A.heapsize = A.heapsize + 1
A[A.heapsize] = ∞
HEAPDECREASEKEY(A, A.heapsize, key)
6.54
Why do we bother setting the key of the inserted node to $\infty$ in line 2 of $\text{MAXHEAPINSERT}$ when the next thing we do is increase its key to the desired value?
In order to pass the guard clause. Otherwise we have to drop the check if $key < A[i]$.
6.55
Argue the correctness of $\text{HEAPINCREASEKEY}$ using the following loop invariant:
At the start of each iteration of the while loop of lines 46, the subarray $A[1 ..A.heap\textsize]$ satisfies the maxheap property, except that there may be one violation: $A[i]$ may be larger than $A[\text{PARENT}(i)]$.
You may assume that the subarray $A[1..A.heap\textsize]$ satisfies the maxheap property at the time $\text{HEAPINCREASEKEY}$ is called.
Initialization: $A$ is a heap except that $A[i]$ might be larger that it's parent, because it has been modified. $A[i]$ is larger than its children, because otherwise the guard clause would fail and the loop will not be entered (the new value is larger than the old value and the old value is larger than the children).
Maintenance: When we exchange $A[i]$ with its parent, the maxheap property is satisfied except that now $A[\text{PARENT}(i)]$ might be larger than its parent. Changing $i$ to its parent maintains the invariant.
Termination: The loop terminates whenever the heap is exhausted or the maxheap property for $A[i]$ and its parent is preserved. At the loop termination, $A$ is a maxheap.
6.56
Each exchange operation on line 5 of $\text{HEAPINCREASEKEY}$ typically requires three assignments. Show how to use the idea of the inner loop of $\text{INSERTIONSORT}$ to reduce the three assignments down to just one assignment.
HEAPINCREASEKEY(A, i, key)
if key < A[i]
error "new key is smaller than current key"
while i > 1 and A[PARENT(i)] < key
A[i] = A[PARENT(i)]
i = PARENT(i)
A[i] = key
6.57
Show how to implement a firstin, firstout queue with a priority queue. Show how to implement a stack with a priority queue. (Queues and stacks are defined in section 10.1).
Both are simple. For a stack we keep adding elements in increasing priority, while in a queue we add them in decreasing priority. For the stack we can set the new priority to $\text{HEAPMAXIMUM}(A) + 1$. For the queue we need to keep track of it and decrease it on every insertion.
Both are not very efficient. Furthermore, if the priority can overflow or underflow, so will eventually need to reassign priorities.
6.58
The operation $\text{HEAPDELETE}(A, i)$ deletes the item in node $i$ from heap $A$. Give an implementation of $\text{HEAPDELETE}$ that runs in $O(\lg n)$ time for an $n$element maxheap.
HEAPDELETE(A, i)
if A[i] > A[h.heapsize]
A[i] = A[A.heapsize]
MAXHEAPIFY(A, i)
else
HEAPINCREASEKEY(A, i, A[A.heapsize])
A.heapsize = A.heapsize  1
Note: The following algorithm is wrong. For example, given an array $A = [15, 7, 9, 1, 2, 3, 8]$ which is a maxheap, and if we delete $A[5] = 2$, then it will fail.
HEAPDELETE(A, i)
A[i] = A[A.heapsize]
A.heapsize = A.heapsize  1
MAXHEAPIFY(A, i)

before:
15 / \ 7 9 / \ / \ 1 2 3 8

after (which is wrong since $8 > 7$ violates the maxheap property):
15 / \ 7 9 / \ / 1 8 3
6.59
Give an $O(n\lg k)$time algorithm to merge $k$ sorted lists into one sorted list, where $n$ is the total number of elements in all the input lists. ($\textit{Hint:}$ Use a minheap for $k$way merging.)
We take one element of each list and put it in a minheap. Along with each element we have to track which list we took it from. When merging, we take the minimum element from the heap and insert another element off the list it came from (unless the list is empty). We continue until we empty the heap.
We have $n$ steps and at each step we're doing an insertion into the heap, which is $\lg k$.