A comparison-based sorting technique based on a Binary Heap data structure. It is similar to selection sort where we first find the maximum element and place the maximum element at the end. We repeat the same process for the remaining elements.
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
{
"arr": "[12, 11, 13, 5, 6, 7]",
"n": 6
}Overview
Heap Sort first rearranges the array into a max-heap: a complete binary tree stored in the array where every parent is at least as large as its children. For index i, the children live at 2i + 1 and 2i + 2, so no pointers are needed.
Once the heap is built, the largest value is at index 0. Heap Sort swaps it to the end of the array, shrinks the heap by one, and calls heapify to sink the new root to its proper level. Repeating this extracts values from largest to smallest, filling the array from the back.
With the default input 12, 11, 13, 5, 6, 7, building the heap moves 13 to the root. Each extraction then fixes one more value at the end — 13, then 12, then 11 — until the array is sorted.
Step by step
- Build a max-heap by calling
heapifyon every non-leaf node fromn/2 - 1down to 0. - Swap the root (the maximum) with the last element of the heap.
- Reduce the heap size by one; the swapped-out maximum is now in its final place.
- Call
heapifyon the root to restore the heap property. - Repeat until the heap has one element.
Complexity
| Case | Cost | Why |
|---|---|---|
| Best case | O(n log n) | Every extraction sifts a value down up to log n levels. |
| Average case | O(n log n) | n extractions at O(log n) each. |
| Worst case | O(n log n) | Guaranteed; building the heap itself is only O(n). |
| Extra space | O(1) | The heap lives inside the input array. |
When to use it
- When you need a worst-case O(n log n) sort with no extra memory, e.g. embedded or real-time systems.
- As the safety net inside Intro Sort when Quick Sort recursion gets too deep.
- When you only need the top k elements: stop after k extractions.
Common mistakes
- It is not stable, and its jumps across the array make it noticeably slower than Quick Sort on real hardware because of cache misses.
- Off-by-one mistakes in the child formulas (
2i/2i + 1belong to 1-based heaps, not 0-based arrays). - Forgetting to pass the shrinking heap size to
heapify, which drags already-sorted values back into the heap.
A dry run is the best way to check your understanding of Heap Sort: follow each row, predict the next one, and compare. The run below takes 146 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
- 12, 11, 13, 5, 6, 7
- Result
- arr = [5, 6, 7, 11, 12, 13], return value = [5, 6, 7, 11, 12, 13]
| Step | Line | Array | What happens |
|---|---|---|---|
| 1 | 2 | [12, 11, 13, 5, 6, 7] | n = 6 |
| 7 | 18 | [12, 11, 13, 5, 6, 7] | n = 6, i = 2, largest = 2, l = 5, r = 6, condition = 5 < 6 && 7 > 13 |
| 8 | 20 | [12, 11, 13, 5, 6, 7] | n = 6, i = 2, largest = 2, l = 5, r = 6, condition = 6 < 6 && undefined > 13 |
| 9 | 22 | [12, 11, 13, 5, 6, 7] | n = 6, i = 2, largest = 2, condition = 2 != 2 |
| 16 | 18 | [12, 11, 13, 5, 6, 7] | n = 6, i = 1, largest = 1, l = 3, r = 4, condition = 3 < 6 && 5 > 11 |
| 17 | 20 | [12, 11, 13, 5, 6, 7] | n = 6, i = 1, largest = 1, l = 3, r = 4, condition = 4 < 6 && 6 > 11 |
| 18 | 22 | [12, 11, 13, 5, 6, 7] | n = 6, i = 1, largest = 1, condition = 1 != 1 |
| 25 | 18 | [12, 11, 13, 5, 6, 7] | n = 6, i = 0, largest = 0, l = 1, r = 2, condition = 1 < 6 && 11 > 12 |
| 26 | 20 | [12, 11, 13, 5, 6, 7] | n = 6, i = 0, largest = 0, l = 1, r = 2, condition = 2 < 6 && 13 > 12 |
| 28 | 22 | [12, 11, 13, 5, 6, 7] | n = 6, i = 0, largest = 2, condition = 2 != 0 |
| 30 | 24 | [13, 11, 13, 5, 6, 7] | n = 6, i = 0, largest = 2, arr[i] = 13 |
| 31 | 25 | [13, 11, 12, 5, 6, 7] | n = 6, i = 0, largest = 2, arr[largest] = 12 |
| 36 | 18 | [13, 11, 12, 5, 6, 7] | n = 6, i = 2, largest = 2, l = 5, r = 6, condition = 5 < 6 && 7 > 12 |
| 37 | 20 | [13, 11, 12, 5, 6, 7] | n = 6, i = 2, largest = 2, l = 5, r = 6, condition = 6 < 6 && undefined > 12 |
| 38 | 22 | [13, 11, 12, 5, 6, 7] | n = 6, i = 2, largest = 2, condition = 2 != 2 |
| 42 | 7 | [7, 11, 12, 5, 6, 7] | n = 6, i = 5, temp = 13, arr[0] = 7 |
| 43 | 8 | [7, 11, 12, 5, 6, 13] | n = 6, i = 5, temp = 13, arr[i] = 13 |
| 48 | 18 | [7, 11, 12, 5, 6, 13] | n = 5, i = 0, largest = 0, l = 1, r = 2, condition = 1 < 5 && 11 > 7 |
| 50 | 20 | [7, 11, 12, 5, 6, 13] | n = 5, i = 0, largest = 1, l = 1, r = 2, condition = 2 < 5 && 12 > 11 |
| 52 | 22 | [7, 11, 12, 5, 6, 13] | n = 5, i = 0, largest = 2, condition = 2 != 0 |
| 54 | 24 | [12, 11, 12, 5, 6, 13] | n = 5, i = 0, largest = 2, arr[i] = 12 |
| 55 | 25 | [12, 11, 7, 5, 6, 13] | n = 5, i = 0, largest = 2, arr[largest] = 7 |
| 60 | 18 | [12, 11, 7, 5, 6, 13] | n = 5, i = 2, largest = 2, l = 5, r = 6, condition = 5 < 5 && 13 > 7 |
| 61 | 20 | [12, 11, 7, 5, 6, 13] | n = 5, i = 2, largest = 2, l = 5, r = 6, condition = 6 < 5 && undefined > 7 |
| 62 | 22 | [12, 11, 7, 5, 6, 13] | n = 5, i = 2, largest = 2, condition = 2 != 2 |
| 66 | 7 | [6, 11, 7, 5, 6, 13] | n = 6, i = 4, temp = 12, arr[0] = 6 |
| 67 | 8 | [6, 11, 7, 5, 12, 13] | n = 6, i = 4, temp = 12, arr[i] = 12 |
| 72 | 18 | [6, 11, 7, 5, 12, 13] | n = 4, i = 0, largest = 0, l = 1, r = 2, condition = 1 < 4 && 11 > 6 |
| 74 | 20 | [6, 11, 7, 5, 12, 13] | n = 4, i = 0, largest = 1, l = 1, r = 2, condition = 2 < 4 && 7 > 11 |
| 75 | 22 | [6, 11, 7, 5, 12, 13] | n = 4, i = 0, largest = 1, condition = 1 != 0 |
| 77 | 24 | [11, 11, 7, 5, 12, 13] | n = 4, i = 0, largest = 1, arr[i] = 11 |
| 78 | 25 | [11, 6, 7, 5, 12, 13] | n = 4, i = 0, largest = 1, arr[largest] = 6 |
| 83 | 18 | [11, 6, 7, 5, 12, 13] | n = 4, i = 1, largest = 1, l = 3, r = 4, condition = 3 < 4 && 5 > 6 |
| 84 | 20 | [11, 6, 7, 5, 12, 13] | n = 4, i = 1, largest = 1, l = 3, r = 4, condition = 4 < 4 && 12 > 6 |
| 85 | 22 | [11, 6, 7, 5, 12, 13] | n = 4, i = 1, largest = 1, condition = 1 != 1 |
| 89 | 7 | [5, 6, 7, 5, 12, 13] | n = 6, i = 3, temp = 11, arr[0] = 5 |
| 90 | 8 | [5, 6, 7, 11, 12, 13] | n = 6, i = 3, temp = 11, arr[i] = 11 |
| 95 | 18 | [5, 6, 7, 11, 12, 13] | n = 3, i = 0, largest = 0, l = 1, r = 2, condition = 1 < 3 && 6 > 5 |
| 97 | 20 | [5, 6, 7, 11, 12, 13] | n = 3, i = 0, largest = 1, l = 1, r = 2, condition = 2 < 3 && 7 > 6 |
| 99 | 22 | [5, 6, 7, 11, 12, 13] | n = 3, i = 0, largest = 2, condition = 2 != 0 |
The remaining 21 key steps follow the same pattern. Press play in the visualizer to watch every step through to the result.