Algorithm Search⌘K

Proofs: Heap extract-max

These are the human proofs of Heap extract-max, at full length.

HEAP-EXTRACT-MAX returns a largest key and leaves a max-heap full

This proof shows: correctness, termination.

Write ss for A.heap-sizeA.\mathit{heap\text{-}size} and p(j)=⌊j/2⌋p(j) = \lfloor j/2 \rfloor. An edge is a pair (p(j),j)(p(j), j) with 2≤j≤s2 \le j \le s, and it holds when A[p(j)]≥A[j]A[p(j)] \ge A[j]. Let C(i)C(i) be the set of children of ii that exist, a subset of {2i,2i+1}\{2i, 2i + 1\} of indices at most ss.

Lemma (MAX-HEAPIFY). Let 1≤i≤s1 \le i \le s and assume

(D) each edge (p(j),j)(p(j), j) with p(j)≠ip(j) \ne i holds, and if i≥2i \ge 2, then A[p(i)]≥A[c]A[p(i)] \ge A[c] for each c∈C(i)c \in C(i).

Then MAX-HEAPIFY(A,i)(A, i) stops after at most ⌊lg⁡(s/i)⌋\lfloor \lg(s/i) \rfloor swaps, only permutes the keys of A[1…s]A[1 \ldots s], and afterwards each edge holds.

Proof. We show that (D) is an invariant of the loop of line L7 for the current ii. It holds at the start. Lines L8 to L10 set mm to an index of a largest key among A[i]A[i] and A[c]A[c] for c∈C(i)c \in C(i): line L9 tests the left child against A[i]A[i], line L10 tests the right child against the larger of the two, and each test is made only for a child that exists.

If m=im = i, then A[i]≥A[c]A[i] \ge A[c] for each c∈C(i)c \in C(i), so the edges out of ii hold, and with (D) every edge holds. Line L11 returns.

Else let x=A[i]x = A[i] and y=A[m]y = A[m], so y>xy > x, and y≥A[t]y \ge A[t] for the other child tt of ii if it exists. Line L12 swaps them. Then the edge (i,m)(i, m) holds because y≥xy \ge x, the edge (i,t)(i, t) holds because y≥A[t]y \ge A[t], and the edge (p(i),i)(p(i), i), if i≥2i \ge 2, holds because (D) gave A[p(i)]≥A[m]=yA[p(i)] \ge A[m] = y. Other edges with an end at ii or mm are the edges out of mm, which (D) for the new value i=mi = m excludes. For the second part of (D) at mm: its parent now holds yy, and each child cc of mm had A[c]≤yA[c] \le y before the swap, because the edges out of mm were not excluded. So (D) holds for the new ii.

Each swap moves ii one level down. The subtree of the first ii has height ⌊lg⁡(s/i)⌋\lfloor \lg(s/i) \rfloor, so there are at most that many swaps, and then the next iteration finds m=im = i, at the latest at a leaf. The only changes are swaps. □\square

Theorem. Let A[1…n]A[1 \ldots n] be a max-heap with n≥1n \ge 1. Then HEAP-EXTRACT-MAX returns a largest key of AA, and afterwards A[1…n−1]A[1 \ldots n - 1] is a max-heap whose multiset of keys is the old one with one copy of the returned key removed. With n=0n = 0 it reports an error. It stops.

Proof. Line L1 handles n=0n = 0. Let n≥1n \ge 1. Each jj has the root 11 as an ancestor, and the edges on the path from 11 to jj hold, so A[1]≥A[j]A[1] \ge A[j] by a chain of inequalities. So μ=A[1]\mu = A[1], saved at line L2, is a largest key. Lines L3 and L4 write the old A[n]A[n] into the root and set s=n−1s = n - 1, so the keys of A[1…s]A[1 \ldots s] are the old keys with one copy of μ\mu removed (if n=1n = 1, the array is empty and the claim holds). Each edge (p(j),j)(p(j), j) with p(j)≠1p(j) \ne 1 and j≤sj \le s joins two cells other than the root, whose keys did not change, so it holds; and the root has no parent. So (D) holds with i=1i = 1, and by the lemma, after line L5 each edge holds and the keys were only permuted. Line L6 returns μ\mu. ■\blacksquare

Back to Heap extract-max