Heaps and Priority Queues

A complete binary tree stored in an array that always gives you the smallest (or largest) item fast.

A binary heap is a complete binary tree that satisfies the heap property:

  • Min-heap: every parent is ≤ its children, so the minimum is at the root.
  • Max-heap: every parent is ≥ its children, so the maximum is at the root.

Because the tree is complete, it fits perfectly in an array with no gaps. For the node at index i (0-indexed):

RelativeIndex
Parent(i − 1) / 2 (integer division)
Left child2i + 1
Right child2i + 2
1index 03index 17index 34index 42index 25index 5
The min-heap [1, 3, 2, 7, 4, 5] drawn as a tree (array index in the note)

Operations

  • insert(x): put x at the end of the array, then sift up: swap it with its parent while it is smaller. O(log n).
  • extractMin(): take the root, move the last element to the root, then sift down: swap it with its smaller child while it is larger. O(log n).
  • peek(): read index 0. O(1).
  • buildHeap(array): sift down every non-leaf from the last one up to the root. Surprisingly, this takes only O(n).
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        MinHeap h = new MinHeap();
        for (int x : new int[]{5, 3, 8, 1, 4, 2}) {
            h.insert(x);
            System.out.println("insert " + x + " -> " + h.data);
        }
        StringBuilder sorted = new StringBuilder();
        while (!h.data.isEmpty()) sorted.append(h.extractMin()).append(' ');
        System.out.println("extract all: " + sorted.toString().trim());
    }
}

class MinHeap {
    List<Integer> data = new ArrayList<>();

    void insert(int x) {
        data.add(x);
        int i = data.size() - 1;
        while (i > 0 && data.get((i - 1) / 2) > data.get(i)) {     // sift up
            swap(i, (i - 1) / 2);
            i = (i - 1) / 2;
        }
    }

    int extractMin() {
        int min = data.get(0);
        int last = data.remove(data.size() - 1);
        if (!data.isEmpty()) {
            data.set(0, last);
            int i = 0;
            while (true) {                                            // sift down
                int l = 2 * i + 1, r = 2 * i + 2, smallest = i;
                if (l < data.size() && data.get(l) < data.get(smallest)) smallest = l;
                if (r < data.size() && data.get(r) < data.get(smallest)) smallest = r;
                if (smallest == i) break;
                swap(i, smallest);
                i = smallest;
            }
        }
        return min;
    }

    private void swap(int a, int b) {
        int t = data.get(a);
        data.set(a, data.get(b));
        data.set(b, t);
    }
}
Output
insert 5 -> [5]
insert 3 -> [3, 5]
insert 8 -> [3, 5, 8]
insert 1 -> [1, 3, 8, 5]
insert 4 -> [1, 3, 8, 5, 4]
insert 2 -> [1, 3, 2, 5, 4, 8]
extract all: 1 2 3 4 5 8

Taking items out one by one gives them in sorted order. That is heapsort: build a heap in O(n), then extract n times at O(log n) each, for O(n log n) total with O(1) extra space when done in place.

The library versions

Both languages ship a ready-made binary min-heap: Java's PriorityQueue and Python's heapq module.

import java.util.Collections;
import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
        for (int x : new int[]{42, 7, 19, 88, 3}) { minHeap.add(x); maxHeap.add(x); }
        System.out.println("smallest: " + minHeap.poll() + ", then " + minHeap.poll());
        System.out.println("largest:  " + maxHeap.poll() + ", then " + maxHeap.poll());
    }
}
Output
smallest: 3, then 7
largest:  88, then 42

GATE-style practice questions

GATE-styleMCQ · one correct answer

The keys 5, 3, 8, 1, 4, 2 are inserted one by one into an empty min-heap (stored in an array, index 0 is the root). What is the array after all insertions?

Show answer and explanationAnswer: B

Inserting 1 sifts it up past 3 to the root, giving 1 3 8 5. 4 stays under 3. 2 is placed at index 5, whose parent is 8 at index 2, so they swap; 2 is larger than the root 1, so it stops: 1 3 2 5 4 8.

GATE-styleNAT · numerical answer

In a max-heap stored in an array with the root at index 1 (1-indexed), what is the index of the parent of the element at index 50?

Show answer and explanationAnswer: 25

With 1-based indexing, the children of i are 2i and 2i + 1, so the parent of i is floor(i / 2) = 25.

GATE-styleMCQ · one correct answer

What is the worst-case time to build a binary heap from an unsorted array of n elements using the bottom-up sift-down method?

Show answer and explanationAnswer: A

Nodes near the bottom, which are most of the nodes, can only sift down a short distance. Summing the heights gives n·Σ h/2^(h+1) = O(n). Inserting the elements one by one would cost O(n log n).

GATE-styleMCQ · one correct answer

In a min-heap of n distinct elements, where can the maximum element be?

Show answer and explanationAnswer: C

A non-leaf node is smaller than its children, so it cannot be the maximum. The maximum must be a leaf, and it can be any leaf, which is why finding the maximum in a min-heap takes Θ(n).