3.4.12 · D4Trees

Exercises — Heap operations — insert O(log n), extract-max - min O(log n), decrease-key

2,557 words12 min readBack to topic

Level 1 — Recognition

Exercise 1.1 — Is it a heap?

Which of these arrays is a valid max-heap? (a) [9, 7, 8, 3, 6, 5, 2] (b) [9, 7, 8, 3, 6, 9, 10] (c) [10, 9, 8, 7, 6, 5, 4]

Recall Solution

Check for every . The figure draws (a) and (b) as trees; every edge must point from a bigger (or equal) parent down to a smaller child.

Figure — Heap operations — insert O(log n), extract-max - min O(log n), decrease-key

(a) parents to check: (parent 0): ✓; : ✓; (parent 1): ✓; : ✓; (parent 2): ✓; : ✓. Every edge good (all green in the figure). Valid.

(b) : parent, , child . ? No — the red edge in the figure marks a child that outranks its parent. Invalid.

(c) every parent child (it is even fully sorted descending, which is always a valid max-heap). Valid.

Answer: (a) and (c).

Exercise 1.2 — Read the family

In array [50, 30, 40, 10, 5, 20], what are the children and parent of index ?

Recall Solution

, . Index 6 is out of range (, valid indices ), so index 2 has one child: . , so parent is .


Level 2 — Application

Exercise 2.1 — Insert trace

Insert into the max-heap [40, 30, 20, 10, 5]. Show every swap.

Recall Solution

Append 45 at index (only legal slot keeping the tree complete): [40,30,20,10,5,45], . Then sift-up — the yellow node climbs one red edge per step in the figure.

Figure — Heap operations — insert O(log n), extract-max - min O(log n), decrease-key
  • parent, . → swap → [40,30,45,10,5,20], .
  • parent, . → swap → [45,30,40,10,5,20], . Stop (root).

Result [45,30,40,10,5,20], 2 swaps.

Exercise 2.2 — Extract-max trace

Perform one extract-max on [45,30,40,10,5,20].

Recall Solution

max . Move last element (20) to root, shrink to : [20,30,40,10,5]. Then sift-down — the yellow root sinks down the branch of its larger child (red arrow).

Figure — Heap operations — insert O(log n), extract-max - min O(log n), decrease-key

sift-down(0): children , . Largest of is at idx 2. → swap → [40,30,20,10,5], .

  • : children idx out of range → no children → stop.

Returns 45, heap becomes [40,30,20,10,5].

Exercise 2.3 — decrease-key trace (min-heap)

Min-heap [3, 9, 5, 14, 10, 8]. Do decrease-key(4, 1) (lower to ).

Recall Solution

Set : [3,9,5,14,1,8], . The lowered key is now too small for its slot → sift-up (min-heap: climb while smaller than parent). Watch the yellow node rise in the figure.

Figure — Heap operations — insert O(log n), extract-max - min O(log n), decrease-key
  • parent, . Min-heap sift-up: → swap → [3,1,5,14,9,8], .
  • parent, . → swap → [1,3,5,14,9,8], . Stop.

Result [1,3,5,14,9,8]; new min = 1 at root.


Level 3 — Analysis

Exercise 3.1 — Build-heap by sift-down

Turn the raw array [3, 9, 2, 1, 4, 5] into a max-heap using bottom-up build-heap (sift-down from index down to ). Show each sift-down.

Recall Solution

, start at , go down to 0. The figure shows the tree at three stages: the raw start, after fixing index 2, and the final max-heap — the yellow node is the one being sifted, red arrows are its swaps, green marks the settled root.

Figure — Heap operations — insert O(log n), extract-max - min O(log n), decrease-key
  • i=2: ; children idx 5 (), idx 6 (none). Largest → swap → [3,9,5,1,4,2]. idx 5 has no children → stop.
  • i=1: ; children idx 3 (), idx 4 (). Largest of → no swap.
  • i=0: ; children idx 1 (), idx 2 (). Largest at idx 1 → swap → [9,3,5,1,4,2], now . Children idx 3 (), idx 4 (). Largest of at idx 4 → swap → [9,4,5,1,3,2], , no children → stop.

Max-heap [9,4,5,1,3,2]. Verify: ; ; . ✓

Exercise 3.2 — Counting swaps

For the insert in Exercise 2.1, the value climbed to the root. What is the maximum number of swaps any single insert can perform in a heap of size , and why?

Recall Solution

A sift-up moves to its parent each swap, so the number of swaps is bounded by the depth of the inserted leaf, which is the tree height . After appending, elements exist, so height . The worst case (new key is the new global max) climbs the full path: swaps. For : — matching the 2 swaps we counted. Answer: .


Level 4 — Synthesis

Exercise 4.1 — Heapsort trace

Using max-heap extraction, sort [3, 1, 4, 1, 5] ascending. Give (a) the built max-heap, then (b) the array after each extract-max writes the max into the freed tail slot.

Recall Solution

(a) Build-heap on [3,1,4,1,5], , start at .

  • i=1: ; children idx 3 (), idx 4 (). Largest at idx 4 → swap → [3,5,4,1,1], idx 4 no children → stop.
  • i=0: ; children idx 1 (), idx 2 (). Largest at idx 1 → swap → [5,3,4,1,1], ; children idx 3 (), idx 4 (); largest → stop.

Built max-heap: [5,3,4,1,1].

(b) Repeated extract-max (swap root with last live slot, shrink, sift-down):

  • Swap : [1,3,4,1,5], live size 4. sift-down(0): children → largest idx2 → swap [4,3,1,1,|5]. → live [4,3,1,1].
  • Swap : [1,3,1,|4,5], size 3. sift-down(0): children idx1 (), idx2 () → largest → swap [3,1,1,|4,5]. → live [3,1,1].
  • Swap : [1,1,|3,4,5], size 2. sift-down(0): child idx1 () → equal, no swap.
  • Swap : [1,|1,3,4,5], size 1. Done.

Sorted: [1,1,3,4,5]. ✓ (Max-heap extraction places each max at the shrinking tail, so the array ends ascending.)

Exercise 4.2 — Dijkstra decrease-key

A min-heap of (distance) keys is [2, 6, 4, 12, 9, 7] for vertices at those indices. A relaxation finds a shorter path to the vertex at index 3, lowering its key . Do the decrease-key, then one extract-min (as Dijkstra pops the closest vertex).

Recall Solution

decrease-key(3, 3): [2,6,4,3,9,7], .

  • parent, . → swap → [2,3,4,6,9,7], .
  • parent, . ? No → stop. Heap: [2,3,4,6,9,7].

extract-min: min . Move last () to root, : [7,3,4,6,9]. sift-down(0):

  • children , . Smallest of at idx1 → swap → [3,7,4,6,9], .
  • children , . Smallest of at idx3 → swap → [3,6,4,7,9], . No children → stop.

Returns 2; heap [3,6,4,7,9].


Level 5 — Mastery

Exercise 5.1 — Delete an arbitrary index

Design (and trace) an algorithm to delete the element at an arbitrary index from a max-heap, in . Test on [45,30,40,10,5,20] deleting index (value ).

Recall Solution

Algorithm: overwrite with the last element , shrink , then restore in whichever direction is now broken: if the moved value is larger than its parent, sift-up(i); otherwise sift-down(i). Only one path is touched → .

Why can only ONE direction break? Before the deletion the heap was valid, so the parent of slot was every node in 's subtree — in particular both of 's children. Now we drop a single new value into slot . Two mutually exclusive cases:

  • If : then is bigger than its parent, but the parent already dominated both children, so — being even bigger — is also both children. The child-inequalities hold; only the parent-inequality can fail → sift-up.
  • If : the parent-inequality holds by assumption; the only possible break is being smaller than a child → only child-inequalities can fail → sift-down. Since "" and "" cannot both hold, at most one direction is ever violated. That is why a single primitive suffices.

Trace: delete idx 2 from [45,30,40,10,5,20]. Last element . Overwrite , : [45,30,20,10,5].

  • Compare with parent, : ? No → the "" case → sift-down.
  • sift-down(2): children idx 5,6 → out of range → no children → stop.

Result [45,30,20,10,5]. (Here 20 already fit both ways, so no swap was needed.)

Exercise 5.2 — Extract-max cost lower bound

Argue that any comparison-based extract-max on a max-heap of elements must, in the worst case, do comparisons — i.e. is tight, not pessimistic.

Recall Solution

Upper bound . After removing the root and promoting the last leaf, sift-down settles the misfit level by level. At each level we must find the largest of three: the node and its two children. That is done with two comparisons — first compare the two children to each other (1 comparison) to find the bigger child, then compare that winner against the node (1 comparison) to decide whether to swap: comparisons per level. The path from root to a leaf has levels, so the total is .

Lower bound . The promoted last-leaf value can be the global minimum. To settle it, sift-down must sink it all the way to a leaf, one level per step, doing comparison per level. That path has length , so it costs comparisons in the worst case.

Together: and . So the bound in the parent note's cost table is tight, not merely an over-cautious upper estimate.


Recall Self-test checklist

Can you insert, extract, and decrease-key without peeking? ::: Trace one of each from a fresh random array; check every parent–child inequality at the end. Do you know why build-heap is not ? ::: Most nodes are shallow; the height-weighted sum converges to . Which primitive does min-heap decrease-key use, and why? ::: sift-up — smaller keys belong nearer the root. After arbitrary-delete, why does only one direction break? ::: The old parent dominated the whole subtree; the new value is either above the parent (only parent-inequality can fail) or below it (only child-inequalities can fail) — never both.