Heap Sort
Build a max-heap, then extract elements one by one.
How it works
Heap Sort works in two phases, both centred on the max-heap property: every parent node is greater than or equal to its children. In Phase 1 the algorithm transforms the raw array into a valid max-heap by calling heapify on every internal node from bottom to top — a process that takes O(n) time. Once the heap is built, arr[0] holds the largest element.
Phase 2 extracts elements in descending order. The root (largest) is swapped with the last element of the unsorted region, shrinking the heap by one and placing that element in its final sorted position. The new root is then sifted down through the reduced heap to restore the heap property. This extraction loop runs n−1 times, and each sift-down takes O(log n) work, giving O(n log n) total for the phase — and therefore O(n log n) overall in all cases.
Unlike Merge Sort, Heap Sort requires no extra memory beyond a few loop variables, making it an in-place O(1)-space algorithm. Unlike Quick Sort, its worst case is also O(n log n), so it provides absolute performance guarantees. The trade-off is poor cache behaviour: the sift-down operation accesses elements at indices 2i+1 and 2i+2, which are far apart for large heaps, leading to many cache misses compared to the sequential access patterns of merge sort or insertion sort.
Complexity
Visualizer
Where it's used in the real world
Linux kernel — lib/sort.c
In-kernel sorting with guaranteed O(n log n) and zero allocationThe Linux kernel cannot call malloc during many critical paths. lib/sort.c implements heapsort because it provides O(n log n) worst-case performance with strictly O(1) auxiliary space — both properties are required in interrupt handlers and memory-constrained kernel contexts where dynamic allocation is forbidden.
C++ std::partial_sort
Retrieving the k smallest elements from a large collectionstd::partial_sort builds a min-heap of size k over the first k elements, then sifts each remaining element through it. Because only k elements need to be sorted, the total cost is O(n log k) rather than O(n log n). This heap-based strategy is the standard implementation choice in libstdc++ and libc++.
Embedded and safety-critical systems
Deterministic sorting with bounded worst-case time and no allocationIn real-time systems (automotive ECUs, avionics, PLCs) algorithms must meet hard timing deadlines. Heap sort's O(n log n) worst-case guarantee — with no dynamic memory allocation and a small, fixed code footprint — makes it a reliable choice when predictability matters more than raw average-case speed.
Implementation
function heapSort(arr: number[]): number[] {
const a = [...arr];
const n = a.length;
// Build max-heap
for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
heapify(a, n, i);
}
// Extract elements one by one
for (let i = n - 1; i > 0; i--) {
[a[0], a[i]] = [a[i], a[0]];
heapify(a, i, 0);
}
return a;
}
function heapify(arr: number[], size: number, root: number): void {
let largest = root;
const left = 2 * root + 1;
const right = 2 * root + 2;
if (left < size && arr[left] > arr[largest]) largest = left;
if (right < size && arr[right] > arr[largest]) largest = right;
if (largest !== root) {
[arr[root], arr[largest]] = [arr[largest], arr[root]];
heapify(arr, size, largest);
}
}
// Usage
console.log(heapSort([38, 27, 43, 3, 9, 82, 10, 55]));
// [3, 9, 10, 27, 38, 43, 55, 82]