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
O(n log n)O(n log n)O(n log n)Space Complexity
O(1)Properties
Algorithm Code
1function heapSort(arr) {2 const n = arr.length;3 4 // Build max heap5 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 one10 for (let i = n - 1; i > 0; i--) {11 // Move current root to end12 [arr[0], arr[i]] = [arr[i], arr[0]];13 14 // Call heapify on the reduced heap15 heapify(arr, i, 0);16 }17 18 return arr;19}20 21function heapify(arr, n, i) {22 let largest = i; // Initialize largest as root23 let left = 2 * i + 1; // Left child24 let right = 2 * i + 2; // Right child25 26 // If left child is larger than root27 if (left < n && arr[left] > arr[largest]) {28 largest = left;29 }30 31 // If right child is larger than largest so far32 if (right < n && arr[right] > arr[largest]) {33 largest = right;34 }35 36 // If largest is not root37 if (largest !== i) {38 [arr[i], arr[largest]] = [arr[largest], arr[i]];39 40 // Recursively heapify the affected sub-tree41 heapify(arr, n, largest);42 }43}Variable State
Call Stack
Array Visualization
Watch how Heap Sort builds a max-heap and then repeatedly extracts the maximum element
Statistics
Legend
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
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);
}
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--;
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.
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.
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
Even with sorted input, heap construction and extraction phases both run in O(n log n).
Average Case
Consistent performance across all input distributions due to heap structure properties.
Worst Case
Unlike quicksort, heap sort never degrades to O(n²) performance.
Detailed Analysis
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
| Algorithm | Time | Space | Stable | Adaptive |
|---|---|---|---|---|
| Heap Sort | O(n log n) | O(1) | ❌ | ❌ |
| Quick Sort | O(n²) worst | O(log n) | ❌ | ❌ |
| Merge Sort | O(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.