Heap Sort

A comparison-based sorting algorithm that uses a binary heap data structure. It builds a max-heap and repeatedly extracts the maximum element.

Algorithm Information

Time Complexity

Best: O(n log n)
Average: O(n log n)
Worst: O(n log n)

Space Complexity

O(1)

Properties

• Unstable sorting algorithm
• In-place sorting
• Consistent O(n log n) performance
• Uses binary heap data structure
1/81
Speed: 1x

Algorithm Code

1function heapSort(arr) {
2 const n = arr.length;
3
4 // Build max heap
5 for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
6 heapify(arr, n, i);
7 }
8
9 // Extract elements from heap one by one
10 for (let i = n - 1; i > 0; i--) {
11 // Move current root to end
12 [arr[0], arr[i]] = [arr[i], arr[0]];
13
14 // Call heapify on the reduced heap
15 heapify(arr, i, 0);
16 }
17
18 return arr;
19}
20
21function heapify(arr, n, i) {
22 let largest = i; // Initialize largest as root
23 let left = 2 * i + 1; // Left child
24 let right = 2 * i + 2; // Right child
25
26 // If left child is larger than root
27 if (left < n && arr[left] > arr[largest]) {
28 largest = left;
29 }
30
31 // If right child is larger than largest so far
32 if (right < n && arr[right] > arr[largest]) {
33 largest = right;
34 }
35
36 // If largest is not root
37 if (largest !== i) {
38 [arr[i], arr[largest]] = [arr[largest], arr[i]];
39
40 // Recursively heapify the affected sub-tree
41 heapify(arr, n, largest);
42 }
43}

Variable State

n:7
i:2
largest:0
left:1
right:2

Call Stack

heapSort

Array Visualization

Watch how Heap Sort builds a max-heap and then repeatedly extracts the maximum element

640
341
252
123
224
115
906

Statistics

Comparisons0
Swaps0
Step1 / 81

Legend

Comparing Elements
Heapifying / Swapping
Sorted (Final Position)
Heap / Unsorted

Starting Heap Sort algorithm. First, we'll build a max-heap from the array.

How Heap Sort Works

Understand heap sort through binary heap concepts, tree structures, and guaranteed O(n log n) performance.

Algorithm Overview

Heap Sort is a comparison-based sorting algorithm that uses a binary heap data structure. It works in two main phases: first building a max-heap from the input data, then repeatedly extracting the maximum element and placing it at the end of the array.

🌳 Binary Heap Structure

A binary heap is a complete binary tree where each parent node is greater than or equal to its children (max-heap). This property ensures that the root always contains the maximum element. The heap is represented as an array where for any element at index i: left child is at 2i+1, right child at 2i+2.

Step-by-Step Process

1

Build Max-Heap

Transform the input array into a max-heap by calling heapify on all non-leaf nodes, starting from the last non-leaf node and working backwards to the root.


for (let i = Math.floor(n/2) - 1; i >= 0; i--) {
  heapify(arr, n, i);
}
2

Extract Maximum

The root (index 0) contains the maximum element. Swap it with the last element of the heap, effectively placing the maximum at its final sorted position.


[arr[0], arr[i]] = [arr[i], arr[0]];

heapSize--;
3

Restore Heap Property

After swapping, the heap property may be violated at the root. Call heapify on the root to restore the max-heap property.

Key Insight: Heapify ensures the largest remaining element bubbles up to the root!
4

Repeat Until Sorted

Repeat steps 2-3 for the remaining heap elements. Each iteration places one more element in its final position and reduces the heap size by one.

for (let i = n-1; i > 0; i--) {
  swap(arr[0], arr[i]);
  heapify(arr, i, 0);
}

The Heapify Process

Heapify is the core operation that maintains the heap property:

function heapify(arr, n, i) {
    let largest = i;          // Initialize largest as root
    let left = 2 * i + 1;     // Left child index
    let right = 2 * i + 2;    // Right child index
    
    // If left child exists and is greater than root
    if (left < n && arr[left] > arr[largest]) {
        largest = left;
    }
    
    // If right child exists and is greater than largest so far
    if (right < n && arr[right] > arr[largest]) {
        largest = right;
    }
    
    // If largest is not root, swap and continue heapifying
    if (largest !== i) {
        [arr[i], arr[largest]] = [arr[largest], arr[i]];
        
        // Recursively heapify the affected sub-tree
        heapify(arr, n, largest);
    }
}

🔄 Heapify Logic

Heapify compares a node with its children and swaps with the larger child if necessary. This process continues recursively down the tree until the heap property is restored. The time complexity of heapify is O(log n) since it may traverse the height of the tree.

Complete Implementation

Here's the complete heap sort implementation:

function heapSort(arr) {
    const n = arr.length;
    
    // Phase 1: Build max heap
    // Start from last non-leaf node and heapify each node
    for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }
    
    // Phase 2: Extract elements from heap one by one
    for (let i = n - 1; i > 0; i--) {
        // Move current root (maximum) to end
        [arr[0], arr[i]] = [arr[i], arr[0]];
        
        // Call heapify on the reduced heap
        heapify(arr, i, 0);
    }
    
    return arr;
}

// Array representation of heap:
// For element at index i:
// - Parent: Math.floor((i-1)/2)
// - Left child: 2*i + 1  
// - Right child: 2*i + 2

// Example:
const numbers = [4, 10, 3, 5, 1];
console.log("Original:", numbers);
heapSort(numbers);
console.log("Sorted:", numbers);

Key Concepts & Properties

✅ Advantages

  • Guaranteed O(n log n): Consistent performance regardless of input
  • In-place sorting: Only requires O(1) extra memory
  • No worst-case degradation: Unlike quicksort's O(n²) worst case
  • Memory efficient: No additional arrays needed
  • Heap data structure: Useful for priority queues

❌ Disadvantages

  • Unstable: Equal elements may change relative order
  • Poor cache performance: Non-sequential memory access
  • Not adaptive: Doesn't benefit from partially sorted data
  • Complex implementation: More complex than simple sorts
  • Slower than quicksort: Higher constant factors in practice

🏗️ Heap Construction

Building the initial heap takes O(n) time, not O(n log n) as might be expected. This is because most nodes are near the bottom of the tree and require fewer comparisons. The mathematical proof shows that the total work is bounded by O(n), making heap sort's total complexity O(n log n).

Complexity Analysis

Best Case

O(n log n)

Even with sorted input, heap construction and extraction phases both run in O(n log n).

Average Case

O(n log n)

Consistent performance across all input distributions due to heap structure properties.

Worst Case

O(n log n)

Unlike quicksort, heap sort never degrades to O(n²) performance.

Detailed Analysis

Heap Construction: O(n) - Building initial max-heap
Extraction Phase: O(n log n) - n extractions × O(log n) heapify each
Heapify Operation: O(log n) - May traverse tree height
Total Operations: O(n) + O(n log n) = O(n log n)
Space Complexity: O(1) - In-place sorting with constant extra space

When to Use Heap Sort

✅ Ideal for:

  • Guaranteed performance: When O(n log n) worst-case is required
  • Memory-constrained systems: In-place sorting with O(1) space
  • Real-time systems: Predictable performance characteristics
  • Priority queue applications: Natural heap structure usage
  • Large datasets: Consistent performance regardless of size
  • Systems programming: When stability isn't required

❌ Avoid for:

  • Stability required: Use merge sort or stable algorithms
  • Cache-sensitive applications: Poor spatial locality
  • Nearly sorted data: Doesn't benefit from existing order
  • Small datasets: Insertion sort may be faster
  • Average-case optimization: Quicksort typically faster

🎯 Perfect Use Case

Heap sort shines in embedded systems and real-time applications where you need guaranteed O(n log n) performance with minimal memory usage. It's also excellent for implementing priority queues and selection algorithms (finding the k largest elements).

Heap Sort vs Other Algorithms

AlgorithmTimeSpaceStableAdaptive
Heap SortO(n log n)O(1)
Quick SortO(n²) worstO(log n)
Merge SortO(n log n)O(n)

Heap sort offers the unique combination of guaranteed O(n log n) time with O(1) space, making it ideal when memory is limited but performance guarantees are needed.