Heap Sort

Builds a max-heap from the array, then repeatedly extracts the maximum. Guaranteed O(n log n) with no extra memory.

Best O(n log n) Avg O(n log n) Worst O(n log n) Space O(1) Stable No In-place Yes Comparison-based

How it works

Heap Sort first builds a max-heap from the array in O(n), then repeatedly swaps the root (the maximum) to the end of the array and sifts the new root down to restore the heap property, shrinking the heap by one each time.

Every extraction costs O(log n) and there are n of them, so the total is a guaranteed O(n log n) with no extra memory.

Implementation

function heapSort(arr) {
  function siftDown(n, i) {
    let largest = i, l = 2*i+1, r = 2*i+2;
    if (l < n && arr[l] > arr[largest]) largest = l;
    if (r < n && arr[r] > arr[largest]) largest = r;
    if (largest !== i) {
      [arr[i], arr[largest]] = [arr[largest], arr[i]];
      siftDown(n, largest);
    }
  }
  for (let i = Math.floor(arr.length/2)-1; i >= 0; i--)
    siftDown(arr.length, i);
  for (let i = arr.length-1; i > 0; i--) {
    [arr[0], arr[i]] = [arr[i], arr[0]];
    siftDown(i, 0);
  }
}

Advantages

  • Guaranteed O(n log n) worst case with O(1) extra memory.
  • No recursion and no pathological inputs.

Disadvantages

  • Not stable.
  • Poor cache locality from the jumpy parent/child index pattern makes it slower than Quick Sort in practice.

When to use it

Use it when you need a hard worst-case bound and cannot spare auxiliary memory — for example as the fallback inside IntroSort.