Algorithm Search⌘K

Proofs: Sift-up

These are the human proofs of Sift-up, at full length.

Sift-up restores the heap property full

This proof shows: correctness, termination.

Write par(j)=⌊(j−1)/2⌋\text{par}(j) = \lfloor (j-1)/2 \rfloor for j≥1j \ge 1. An edge is a pair (par(c),c)(\text{par}(c), c) with 1≤c<n1 \le c < n. The edge is right when A[par(c)]≤A[c]A[\text{par}(c)] \le A[c]. The array is a min-heap when all edges are right.

Theorem. Let A[0…n−1]A[0 \ldots n-1] and 0≤i<n0 \le i < n satisfy (H1) every edge (par(c),c)(\text{par}(c), c) with c≠ic \ne i is right, and (H2) if i≥1i \ge 1, then A[par(i)]≤A[c]A[\text{par}(i)] \le A[c] for each child cc of ii. Then SIFT-UP(A,i)(A, i) ends after at most ⌊lg⁡(i+1)⌋\lfloor \lg(i+1) \rfloor iterations. At the end, AA is a min-heap, it is a permutation of the input, and only the cells on the path from the input ii to the root have changed.

Proof. We show that this invariant holds before each test of line L1:

(I) (H1) and (H2) hold for the current value of ii. The array is a permutation of the input, and each changed cell is on the path from the input index to the root.

Initialization. Before the first test, (I) is the hypothesis of the theorem, and no cell has changed.

Maintenance. Assume (I) and i>0i > 0. Line L2 sets p=par(i)p = \text{par}(i). If line L3 finds A[p]≤A[i]A[p] \le A[i], the procedure returns; we treat that case under termination. Else A[p]>A[i]A[p] > A[i]. Write a=A[i]a = A[i] and b=A[p]b = A[p] before line L4, so a<ba < b. After line L4, A[p]=aA[p] = a and A[i]=bA[i] = b. We check each edge that has pp or ii as an end. All other edges keep both values, so they stay as they were.

  1. The edge (p,i)(p, i): A[p]=a<b=A[i]A[p] = a < b = A[i], so it is right.
  2. An edge (i,c)(i, c) for a child cc of ii: before the swap, (H2) gave b=A[par(i)]≤A[c]b = A[\text{par}(i)] \le A[c]. Now A[i]=bA[i] = b, so the edge is right.
  3. The edge (p,s)(p, s) for the other child ss of pp, if it exists: before the swap the edge was right by (H1), because s≠is \ne i, so b≤A[s]b \le A[s]. Now A[p]=a<b≤A[s]A[p] = a < b \le A[s], so it is right.
  4. The edge (par(p),p)(\text{par}(p), p), if p≥1p \ge 1: this is the one edge that (H1) for the new index pp leaves out.

So each edge whose child is not pp is right, which is (H1) for pp. For (H2) with p≥1p \ge 1: the edge (par(p),p)(\text{par}(p), p) was right before the swap by (H1), because p≠ip \ne i, so A[par(p)]≤bA[\text{par}(p)] \le b. The children of pp are now ii, with value bb, and ss, with A[s]≥bA[s] \ge b by step 3. Both are at least A[par(p)]A[\text{par}(p)], which did not change. So (H2) holds for pp. A swap keeps the multiset of the items, and pp is on the path from the input index to the root. Line L5 sets i←pi \leftarrow p, so (I) holds before the next test.

Termination. Each iteration that does not return replaces ii by par(i)\text{par}(i). For j≥1j \ge 1, ⌊lg⁡(par(j)+1)⌋=⌊lg⁡(j+1)⌋−1\lfloor \lg(\text{par}(j)+1) \rfloor = \lfloor \lg(j+1) \rfloor - 1, because par(j)+1=⌊(j+1)/2⌋\text{par}(j) + 1 = \lfloor (j+1)/2 \rfloor. So the depth ⌊lg⁡(i+1)⌋\lfloor \lg(i+1) \rfloor drops by exactly 1 in each such iteration, and it is never negative. Hence there are at most ⌊lg⁡(i+1)⌋\lfloor \lg(i+1) \rfloor iterations, counted from the input ii.

The procedure stops in one of two ways. At line L3, A[par(i)]≤A[i]A[\text{par}(i)] \le A[i], so the edge that (H1) leaves out is right too, and all edges are right. At line L1 with i=0i = 0, no edge has the child 00, so (H1) already covers all edges. In both cases AA is a min-heap, and by (I) it is a permutation of the input that changed only on the path. ■\blacksquare

HEAP-INSERT. Before line L7, all edges of A[0…n−1]A[0 \ldots n-1] are right. After line L7 the new index nn has no children, and all edges except (par(n),n)(\text{par}(n), n) are old edges. So (H1) and (H2) hold for i=ni = n, and the theorem applies to the call of line L8.

Decrease-key. If AA is a min-heap and the value at ii is lowered from bb to a≤ba \le b, then each edge (i,c)(i, c) stays right, because a≤b≤A[c]a \le b \le A[c], and A[par(i)]≤b≤A[c]A[\text{par}(i)] \le b \le A[c] gives (H2). So the theorem applies to SIFT-UP(A,i)(A, i).

Back to Sift-up