Lesson
The theory — Binary Heap: A Priority Queue in an Array
A binary min-heap is an array in which the key at each position i is no larger than the keys at positions 2i + 1 and 2i + 2, its children; the parent of position i is ⌊(i − 1) / 2⌋. Read that way, the array is a complete binary tree, and the smallest key is always at position 0, the root. To insert, put the key at the end and sift it up, swapping it with its parent while it is the smaller. To take out the smallest, move the last key to the root and sift it down, swapping it with its smaller child while that child is smaller. A heap used this way is a priority queue.
What each symbol means
n- the number of keys in the heap
i- a position in the array, counted from 0
h- the height of a position: how many levels lie below it, ⌊log₂(n / (i + 1))⌋
- Assumes
- A comparison is one key tested against another, and a swap exchanges two positions; moving the last key to the root during an extract is neither. A key equal to its parent, or to its smaller child, stays where it is, and between two equal children the left one is taken. The heap keeps the smallest key on top; a max-heap is the same with every comparison reversed. Up to fifteen keys from 0 to 99, so the whole tree fits on a phone. The orders counted in the last row are of different keys.
Problem solved in full
-
How many comparisons does each build cost at a thousand keys? 4 steps
Press Largest first, one at a time and then Largest first, from the last parent, and explain the 34 and the 22. Then take 1,023 keys arriving largest first. How many comparisons does each method make?
-
Position i sits at depth ⌊log₂(i + 1)⌋: one position at depth 0, two at 1, four at 2, eight at 3. Arriving largest first, each new key is the smallest so far and climbs to the root, one comparison and one swap per level: 0 + 2 · 1 + 4 · 2 + 8 · 3 = 34.
-
From the last parent, what counts is height: 3 for the root, 2 for positions 1 and 2, 1 for the four at depth 2, 0 for the eight leaves, 11 in all. Largest first, every key sinks the whole way, and with fifteen keys every parent has two children, so each level costs two comparisons: 22 comparisons, 11 swaps.
-
1,023 = 2¹⁰ − 1 is a full tree of ten levels, with 2ᵈ positions at depth d. One at a time costs the sum of the depths: 1 · 2 + 2 · 4 + 3 · 8 + ⋯ + 9 · 512 = 8,194 comparisons, and as many swaps.
-
From the last parent costs twice the sum of the heights. There are 2⁹ positions of height 0, 2⁸ of height 1, and so on up to the root at height 9: 1 · 256 + 2 · 128 + ⋯ + 9 · 1 = 1,013, which is 1,023 minus the ten 1s in its binary form. Twice that is 2,026 comparisons, with 1,013 swaps.
Answer
8,194 comparisons one at a time, 2,026 from the last parent, about eight per key against two. Most of a heap's positions are deep and short: insertion pays for the depth, the build from the last parent pays for the height. The tool stops at fifteen keys, where the same arithmetic gives the 34 and 22 it prints.
-
Learning path
What a data structure makes cheap
References (2)
- Heapsort as first published: J. W. J. Williams, "Algorithm 232: Heapsort," Communications of the ACM 7(6), 347–348, June 1964.
- The heap-based sort published six months later, close to the version used today: Robert W. Floyd, "Algorithm 245: Treesort 3," Communications of the ACM 7(12), 701, December 1964.