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
  1. Definition
  2. Array representation
  3. Operations
  4. Build-heap in linear time
  5. Heapsort
  6. Where can the kkkth largest be?
  7. Heaps with ddd children
  8. Cost summary
  9. Worked examples
  10. Common traps
  11. Quick revision

Definition

A binary heap is a binary tree with two properties:

  1. Shape: it is a complete binary tree. Every level is full except possibly the last, which is filled from left to right.
  2. 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 nn nodes has height ⌊log⁡2n⌋\lfloor \log_2 n \rfloor.
  • It has ⌈n/2⌉\lceil n/2 \rceil leaves and ⌊n/2⌋\lfloor n/2 \rfloor 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 ii 2i+12i + 1 2i2i
Right child of ii 2i+22i + 2 2i+12i + 1
Parent of ii ⌊(i−1)/2⌋\lfloor (i - 1)/2 \rfloor ⌊i/2⌋\lfloor i/2 \rfloor
Leaves indices ⌊n/2⌋..n−1\lfloor n/2 \rfloor .. n-1 indices ⌊n/2⌋+1..n\lfloor n/2 \rfloor + 1 .. n

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 ii except the root. That is n−1n - 1 comparisons.

Operations

Insert (sift-up)

Place the new key in the next free slot (index nn) 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 ⌊log⁡2n⌋\lfloor \log_2 n \rfloor swaps: O(log⁡n)O(\log n).

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 2log⁡2n2 \log_2 n comparisons: O(log⁡n)O(\log n).

Other operations

  • Increase-key in a max-heap: change the key and sift up. O(log⁡n)O(\log n).
  • Decrease-key in a max-heap: change the key and sift down. O(log⁡n)O(\log n).
  • Delete an arbitrary position: replace it with the last element, then sift up or down as needed. O(log⁡n)O(\log n), given the position.
  • Search for a key: no ordering guides you, so Θ(n)\Theta(n).
  • Find the minimum of a max-heap: it is among the ⌈n/2⌉\lceil n/2 \rceil leaves, so Θ(n)\Theta(n).

Build-heap in linear time

Inserting nn keys one by one costs O(nlog⁡n)O(n \log n). 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 (⌊n/2⌋−1\lfloor n/2 \rfloor - 1 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 O(n)O(n): a node at height kk sifts down at most kk levels, and there are at most ⌈n/2k+1⌉\lceil n / 2^{k+1} \rceil nodes at height kk. So the total work is

∑k=0⌊log⁡2n⌋n2k+1⋅O(k)=O(n∑k≥0k2k)=O(2n)=O(n)\sum_{k=0}^{\lfloor \log_2 n \rfloor} \frac{n}{2^{k+1}} \cdot O(k) = O\Big(n \sum_{k \ge 0} \frac{k}{2^k}\Big) = O(2n) = O(n)

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 Θ(nlog⁡n)\Theta(n \log n) in every case.
  • In place, O(1)O(1) extra space.
  • Not stable.

Where can the kkth 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 kkth largest has depth at most k−1k - 1, so it lies in the first 2k−12^k - 1 positions.
  • The smallest is a leaf.

Finding the kkth largest without destroying the heap can be done in O(klog⁡k)O(k \log k) with an auxiliary heap of candidates.

Heaps with dd children

In a dd-ary heap stored 0-based, the children of ii are di+1,…,di+ddi + 1, \ldots, di + d and the parent of ii is ⌊(i−1)/d⌋\lfloor (i - 1)/d \rfloor. Height is about log⁡dn\log_d n. Insert gets cheaper (O(log⁡dn)O(\log_d n)), while delete-max gets more expensive (O(dlog⁡dn)O(d \log_d n)) because each level must look at dd children.

Cost summary

Operation Binary heap
Find max (max-heap) O(1)O(1)
Insert O(log⁡n)O(\log n)
Delete max O(log⁡n)O(\log n)
Increase or decrease key (position known) O(log⁡n)O(\log n)
Build from nn keys, bottom-up O(n)O(n)
Build by nn insertions O(nlog⁡n)O(n \log n)
Search or find min (max-heap) Θ(n)\Theta(n)
Merge two heaps of size nn O(n)O(n) 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] (n=8n = 8, 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 n=5n = 5 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: (43)=4\binom{4}{3} = 4 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 4×2×1=84 \times 2 \times 1 = 8.

The general recurrence is H(n)=(n−1L)H(L)H(R)H(n) = \binom{n-1}{L} H(L) H(R), where LL and RR 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 O(nlog⁡n)O(n \log n). The bottom-up method is O(n)O(n).
  • Thinking a heap supports search in O(log⁡n)O(\log n).

Quick revision

  • Complete tree plus heap order; height ⌊log⁡2n⌋\lfloor \log_2 n \rfloor; ⌈n/2⌉\lceil n/2 \rceil leaves.
  • 0-based: children 2i+12i + 1, 2i+22i + 2, parent ⌊(i−1)/2⌋\lfloor (i-1)/2 \rfloor. 1-based: children 2i2i, 2i+12i + 1, parent ⌊i/2⌋\lfloor i/2 \rfloor.
  • Insert sifts up, delete-max sifts down with the larger child, both O(log⁡n)O(\log n).
  • Bottom-up build-heap is O(n)O(n); repeated insertion is O(nlog⁡n)O(n \log n).
  • Heapsort: Θ(nlog⁡n)\Theta(n \log n), in place, not stable.
  • Second largest at index 1 or 2; minimum at some leaf; search Θ(n)\Theta(n).
  • dd-ary heap, 0-based: parent of ii is ⌊(i−1)/d⌋\lfloor (i-1)/d \rfloor.

Further reading

Test this section