Section 4 · 8 min read
Binary heaps
The binary heap as a complete tree in an array: index arithmetic, insertion, deletion, linear-time build-heap, heapsort, d-ary heaps and the questions GATE builds on them.
On this page
Definition
A binary heap is a binary tree with two properties:
- Shape: it is a complete binary tree. Every level is full except possibly the last, which is filled from left to right.
- Order: in a max-heap every node's key is at least the keys of its children; in a min-heap it is at most. Equal keys are allowed.
The order property relates only a node and its descendants. Siblings and cousins are not ordered with respect to each other, which is why a heap is not a search structure.
Consequences:
- The maximum of a max-heap is at the root.
- A heap with nodes has height .
- It has leaves and internal nodes.
- Every path from the root to a leaf is sorted (non-increasing for a max-heap).
Array representation
Because the tree is complete, it fits in an array with no gaps, level by level.
| 0-based (root at 0) | 1-based (root at 1) | |
|---|---|---|
| Left child of | ||
| Right child of | ||
| Parent of | ||
| Leaves | indices | indices |
Check which convention a question uses before computing anything. Most GATE heap questions use 0-based arrays when they show C code and 1-based when they show pseudo-code.
To test whether an array is a max-heap, check a[parent(i)] >= a[i] for every except the root. That is comparisons.
Operations
Insert (sift-up)
Place the new key in the next free slot (index ) so the shape stays complete. Then, while it is larger than its parent, swap it with the parent.
void insert(int h[], int *n, int x) {
int i = (*n)++;
h[i] = x;
while (i > 0 && h[(i - 1) / 2] < h[i]) {
int t = h[i]; h[i] = h[(i - 1) / 2]; h[(i - 1) / 2] = t;
i = (i - 1) / 2;
}
}
At most swaps: .
Delete-max (sift-down)
Save the root, move the last element to the root, shrink the heap, and push the root down: while it is smaller than its larger child, swap with that child.
void siftDown(int h[], int n, int i) {
for (;;) {
int l = 2 * i + 1, r = l + 1, m = i;
if (l < n && h[l] > h[m]) m = l;
if (r < n && h[r] > h[m]) m = r;
if (m == i) return;
int t = h[i]; h[i] = h[m]; h[m] = t;
i = m;
}
}
int deleteMax(int h[], int *n) {
int top = h[0];
h[0] = h[--(*n)];
siftDown(h, *n, 0);
return top;
}
Each level costs two comparisons (find the larger child, then compare with it), so delete-max uses at most about comparisons: .
Other operations
- Increase-key in a max-heap: change the key and sift up. .
- Decrease-key in a max-heap: change the key and sift down. .
- Delete an arbitrary position: replace it with the last element, then sift up or down as needed. , given the position.
- Search for a key: no ordering guides you, so .
- Find the minimum of a max-heap: it is among the leaves, so .
Build-heap in linear time
Inserting keys one by one costs . The bottom-up method is faster: treat the array as a complete tree and call sift-down on every internal node from the last one ( in 0-based indexing) back to the root.
void buildHeap(int h[], int n) {
for (int i = n / 2 - 1; i >= 0; i--)
siftDown(h, n, i);
}
Why it is : a node at height sifts down at most levels, and there are at most nodes at height . So the total work is
The two methods can produce different arrays from the same input. Questions say which method to use; read carefully.
Heapsort
Build a max-heap, then repeatedly swap the root with the last element of the heap, shrink the heap by one and sift down the new root. The array ends sorted in increasing order.
- Time in every case.
- In place, extra space.
- Not stable.
Where can the th largest be?
In a max-heap with distinct keys:
- The largest is at the root (index 0).
- The second largest is a child of the root: index 1 or 2.
- The third largest is at depth 1 or 2: any of indices 1 to 6.
- In general, the th largest has depth at most , so it lies in the first positions.
- The smallest is a leaf.
Finding the th largest without destroying the heap can be done in with an auxiliary heap of candidates.
Heaps with children
In a -ary heap stored 0-based, the children of are and the parent of is . Height is about . Insert gets cheaper (), while delete-max gets more expensive () because each level must look at children.
Cost summary
| Operation | Binary heap |
|---|---|
| Find max (max-heap) | |
| Insert | |
| Delete max | |
| Increase or decrease key (position known) | |
| Build from keys, bottom-up | |
| Build by insertions | |
| Search or find min (max-heap) | |
| Merge two heaps of size | by rebuilding |
Worked examples
Worked example 1: inserting into a min-heap
Insert 40, 25, 30, 10, 5, 35, 15 one at a time into an empty min-heap (0-based array).
- 40:
[40]. - 25 is smaller than parent 40, swap:
[25, 40]. - 30 at index 2, parent 25: stays.
[25, 40, 30]. - 10 at index 3, parent 40: swap; at index 1, parent 25: swap.
[10, 25, 30, 40]. - 5 at index 4, parent 25: swap; at index 1, parent 10: swap.
[5, 10, 30, 40, 25]. - 35 at index 5, parent 30: stays.
- 15 at index 6, parent 30: swap; at index 2, parent 5: stays.
Final: [5, 10, 15, 40, 25, 35, 30].
Worked example 2: bottom-up build-heap with swap count
Build a max-heap from [3, 1, 6, 5, 2, 4, 9, 7] (, sift-down on indices 3, 2, 1, 0).
- Index 3 (5): child 7. Swap.
[3, 1, 6, 7, 2, 4, 9, 5](1 swap) - Index 2 (6): children 4, 9. Swap with 9.
[3, 1, 9, 7, 2, 4, 6, 5](2) - Index 1 (1): children 7, 2. Swap with 7; now at index 3 with child 5, swap again.
[3, 7, 9, 5, 2, 4, 6, 1](4) - Index 0 (3): children 7, 9. Swap with 9; now at index 2 with children 4, 6, swap with 6.
[9, 7, 6, 5, 2, 4, 3, 1](6)
Result [9, 7, 6, 5, 2, 4, 3, 1] after 6 swaps.
Worked example 3: one delete-max
Delete the maximum from [9, 7, 6, 5, 2, 4, 3, 1]. Move the last element 1 to the root: [1, 7, 6, 5, 2, 4, 3]. Its larger child is 7, swap: [7, 1, 6, 5, 2, 4, 3]. At index 1 the children are 5 and 2; swap with 5: [7, 5, 6, 1, 2, 4, 3]. Index 3 has no children in a heap of 7. Done.
Worked example 4: how many max-heaps on 1 to 5?
The shape for is fixed: the root, a left subtree of 3 nodes and a right subtree of 1 node. The root must be 5. Choose which 3 of the remaining 4 keys go left: ways. A 3-node heap with given keys can be arranged in 2 ways (largest on top, the other two in either order), and a 1-node heap in 1 way. Total .
The general recurrence is , where and are the sizes of the left and right subtrees of the complete tree.
Common traps
- Mixing 0-based and 1-based parent and child formulas.
- Swapping with the first child instead of the larger child during sift-down.
- Using one-by-one insertion when the question asks for bottom-up build-heap (or the reverse); the arrays differ.
- Assuming the smallest element of a max-heap is at the last index. It can be at any leaf.
- Saying build-heap is . The bottom-up method is .
- Thinking a heap supports search in .
Quick revision
- Complete tree plus heap order; height ; leaves.
- 0-based: children , , parent . 1-based: children , , parent .
- Insert sifts up, delete-max sifts down with the larger child, both .
- Bottom-up build-heap is ; repeated insertion is .
- Heapsort: , in place, not stable.
- Second largest at index 1 or 2; minimum at some leaf; search .
- -ary heap, 0-based: parent of is .