Algorithm Search⌘K

Proofs: Heap construction by insertion

These are the human proofs of Heap construction by insertion, at full length.

BUILD-BY-INSERTION makes the array a max-heap full

This proof shows: correctness, termination.

Write p(j)=⌊j/2⌋p(j) = \lfloor j/2 \rfloor. For m≤nm \le n, an edge of the prefix A[1…m]A[1 \ldots m] is a pair (p(j),j)(p(j), j) with 2≤j≤m2 \le j \le m, and it holds when A[p(j)]≥A[j]A[p(j)] \ge A[j]. The prefix is a max-heap when each of its edges holds. Let Cm(i)C_m(i) be the set of children of ii that are at most mm.

Outer invariant. Before the test of line L1 with the value jj, the prefix A[1…j−1]A[1 \ldots j - 1] is a max-heap, and AA is a permutation of the input.

Initialization. For j=2j = 2, the prefix A[1…1]A[1 \ldots 1] has no edges.

Maintenance. Fix jj and consider lines L2 to L5 with m=jm = j. Before each test of line L3, we claim:

(I) each edge (p(t),t)(p(t), t) of A[1…j]A[1 \ldots j] with t≠it \ne i holds, and if i≥2i \ge 2, then A[p(i)]≥A[c]A[p(i)] \ge A[c] for each c∈Cj(i)c \in C_j(i).

When line L2 sets i=ji = j, the cell jj has no children in A[1…j]A[1 \ldots j], because 2j>j2j > j. The edges of A[1…j]A[1 \ldots j] other than (p(j),j)(p(j), j) are the edges of A[1…j−1]A[1 \ldots j - 1], which hold by the outer invariant. The second part holds because Cj(j)C_j(j) is empty. So (I) holds.

Let the test of line L3 be true, so i≥2i \ge 2 and, with q=p(i)q = p(i), x=A[q]<A[i]=yx = A[q] < A[i] = y. Line L4 swaps them. We check the edges with an end at qq or ii, except the edge into qq.

  • The edge (q,i)(q, i) now holds, since y>xy > x.
  • For c∈Cj(i)c \in C_j(i), the edge (i,c)(i, c): by the second part of (I), x≥A[c]x \ge A[c], and A[c]A[c] did not change.
  • For the other child tt of qq, if t≤jt \le j: the edge (q,t)(q, t) held before, so A[t]≤x<yA[t] \le x < y.

Line L5 sets i=qi = q. So each edge except the one into the new ii holds. If the new i≥2i \ge 2, the edge (p(q),q)(p(q), q) held before the swap, since it was not the edge into the old ii; so A[p(q)]≥x≥A[t]A[p(q)] \ge x \ge A[t], and the children of qq now hold xx and A[t]A[t]. So (I) holds again.

Each iteration halves ii, so the inner loop stops after at most ⌊lg⁡j⌋\lfloor \lg j \rfloor iterations. When it stops, either i=1i = 1, which has no edge into it, or A[p(i)]≥A[i]A[p(i)] \ge A[i]. With (I), each edge of A[1…j]A[1 \ldots j] holds, so A[1…j]A[1 \ldots j] is a max-heap. The loop only swaps cells, so AA is still a permutation of the input. This is the outer invariant for j+1j + 1.

Termination. The outer loop runs for j=2,…,nj = 2, \ldots, n, and each inner loop stops, as shown. When the outer loop ends, j=n+1j = n + 1, and the outer invariant says that A[1…n]A[1 \ldots n] is a max-heap.

Theorem. For each array A[1…n]A[1 \ldots n] with n≥0n \ge 0, BUILD-BY-INSERTION(A,n)(A, n) stops, and after it AA is a max-heap that is a permutation of the input. Moreover, after the iteration with the value jj, the prefix A[1…j]A[1 \ldots j] is a max-heap, and the iteration does not read or write a cell beyond jj.

Proof. The first two claims are the invariant at the end and termination. The last claim holds because the inner loop reads and writes only the cells ii and p(i)p(i) with i≤ji \le j. So the method is online: it can run while the keys arrive. ■\blacksquare

Back to Heap construction by insertion