A Min-Heap is a specialized tree-based data structure that satisfies the heap property: the value of each node is less than or equal to the value of its children. This means the smallest element is always at the root. It is commonly used to implement priority queues.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
{
"status": "Starting to build Min-Heap..."
}Overview
A min-heap is a complete binary tree in which every parent is smaller than or equal to its children, so the smallest value is always at the root. 'Complete' means every level is full except possibly the last, which fills from left to right. That shape lets the tree live in a plain array: the children of index i are at 2i + 1 and 2i + 2, and its parent is at floor((i - 1) / 2).
Building a heap from an arbitrary array is done bottom-up: call heapify (sift-down) on every non-leaf node, from the last one back to the root. Surprisingly, this takes only O(n) time, because most nodes are near the bottom and sink only a short distance.
With the default input 10, 20, 15, 30, 40, 5, 50, 1, building the heap pulls 1 up to the root through swaps with 30, 20 and 10, and 5 rises above 15. The visualizer then demonstrates extractMin: it removes 1, moves the last element (30) to the root, and sinks it back down until the heap property holds again.
Step by step
- To build: for
ifromfloor(n / 2) - 1down to 0, callheapify(arr, n, i). heapifycompares a node with its children and swaps it with the smaller child if that child is smaller, then repeats from the child's position.- To extract the minimum: save
arr[0], move the last element to index 0, shrink the heap, andheapifyfrom the root. - To insert (not shown): append the value and sift it up while it is smaller than its parent.
Complexity
| Case | Cost | Why |
|---|---|---|
| Build heap | O(n) | Sum of node heights is linear, even though each heapify can be O(log n). |
| Get minimum | O(1) | It is always at index 0. |
| Extract min / insert | O(log n) | One path from root to leaf or leaf to root. |
| Space | O(n) | The array itself; no pointers needed. |
When to use it
- Priority queues: task schedulers, event simulation, and Dijkstra's and Prim's algorithms.
- Streaming 'top k' problems — keep a min-heap of size k to track the k largest items seen so far.
- Merging k sorted lists by repeatedly taking the smallest head.
Common mistakes
- A heap is not sorted: only the root is guaranteed to be the minimum. Searching for an arbitrary value is still O(n).
- Building a heap by inserting elements one at a time is O(n log n); bottom-up heapify is O(n).
- Using 1-based child formulas (
2i,2i + 1) on a 0-based array.
A dry run is the best way to check your understanding of Min-Heap: follow each row, predict the next one, and compare. The run below takes 103 steps in total. Steps that only re-print loop counters are left out so the decisions stand out. The Line column refers to the line numbers in the code listing above.
- Input
- 10,20,15,30,40,5,50,1
- Result
- status = Extraction complete, returned_min = 1, final_heap = [5, 10, 15, 20, 40, 30, 50]
| Step | Line | What happens |
|---|---|---|
| 1 | 19 | status = Starting to build Min-Heap... |
| 2 | 2 | status = Heapifying at index 3, node_value = 30 |
| 6 | 7 | condition = 7 < 8 && 1 < 30 |
| 8 | 10 | condition = 8 < 8 && undefined < 1 |
| 9 | 13 | condition = 7 !== 3 |
| 10 | 14 | action = Swapping 30 and 1 |
| 11 | 2 | status = Heapifying at index 7, node_value = 30 |
| 15 | 7 | condition = 15 < 8 && undefined < 30 |
| 16 | 10 | condition = 16 < 8 && undefined < 30 |
| 17 | 13 | condition = 7 !== 7 |
| 18 | 15 | action = Recursively heapify on new subtree |
| 19 | 2 | status = Heapifying at index 2, node_value = 15 |
| 23 | 7 | condition = 5 < 8 && 5 < 15 |
| 25 | 10 | condition = 6 < 8 && 50 < 5 |
| 26 | 13 | condition = 5 !== 2 |
| 27 | 14 | action = Swapping 15 and 5 |
| 28 | 2 | status = Heapifying at index 5, node_value = 15 |
| 32 | 7 | condition = 11 < 8 && undefined < 15 |
| 33 | 10 | condition = 12 < 8 && undefined < 15 |
| 34 | 13 | condition = 5 !== 5 |
| 35 | 15 | action = Recursively heapify on new subtree |
| 36 | 2 | status = Heapifying at index 1, node_value = 20 |
| 40 | 7 | condition = 3 < 8 && 1 < 20 |
| 42 | 10 | condition = 4 < 8 && 40 < 1 |
| 43 | 13 | condition = 3 !== 1 |
| 44 | 14 | action = Swapping 20 and 1 |
| 45 | 2 | status = Heapifying at index 3, node_value = 20 |
| 49 | 7 | condition = 7 < 8 && 30 < 20 |
| 50 | 10 | condition = 8 < 8 && undefined < 20 |
| 51 | 13 | condition = 3 !== 3 |
| 52 | 15 | action = Recursively heapify on new subtree |
| 53 | 2 | status = Heapifying at index 0, node_value = 10 |
| 57 | 7 | condition = 1 < 8 && 1 < 10 |
| 59 | 10 | condition = 2 < 8 && 5 < 1 |
| 60 | 13 | condition = 1 !== 0 |
| 61 | 14 | action = Swapping 10 and 1 |
| 62 | 2 | status = Heapifying at index 1, node_value = 10 |
| 66 | 7 | condition = 3 < 8 && 20 < 10 |
| 67 | 10 | condition = 4 < 8 && 40 < 10 |
| 68 | 13 | condition = 1 !== 1 |
The remaining 22 key steps follow the same pattern. Press play in the visualizer to watch every step through to the result.