Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

Heap Sort Algorithm max heap, heapify: Tutorial, Examples, FAQs & Interview Tips

What is a Heap?

A heap is a special tree-based data structure that is usually implemented as an array. It is a complete binary tree, which means all levels are completely filled except possibly the last level, and the last level is filled from left to right.

There are two common types:

  • Max-Heap: every parent is greater than or equal to its children, so the root contains the maximum element.
  • Min-Heap: every parent is less than or equal to its children, so the root contains the minimum element.

For a node at index i in a 0-indexed array:

  • left child = 2i + 1
  • right child = 2i + 2
  • parent = (i - 1) / 2

Why Heaps Are Useful

Heaps are useful when we repeatedly need the largest or smallest element. Because the root always stores the extreme value, insertion and deletion can be done efficiently in O(log n).

Heaps are widely used in:

  • priority queues,
  • Heap Sort,
  • Dijkstra's algorithm,
  • Prim's algorithm,
  • scheduling and event simulation problems.

What is Heap Sort?

Heap Sort is a comparison-based sorting algorithm that uses a max-heap to sort elements in ascending order.

It has two main phases:

  1. Build a max-heap from the given array.
  2. Repeatedly extract the maximum by swapping the root with the last element, shrinking the heap, and restoring the heap property.

The result is a sorted array in-place.

Core Idea of Heap Sort

If the array is arranged as a max-heap, then the largest element is always at the root. So:

  • move the root to the end of the array,
  • reduce the heap size by one,
  • heapify the root again to restore the max-heap.

Repeating this places the elements from largest to smallest at the end of the array, which gives ascending order overall.

Time and Space Complexity

Case Time Space Stable?
Best O(n log n) O(1) No
Average O(n log n) O(1) No
Worst O(n log n) O(1) No

Heap Sort is valued because its worst-case time is guaranteed to stay O(n log n), unlike Quick Sort which can degrade to O(n^2) in the worst case.

Why Build-Heap Is O(n)

At first glance, it may seem that building a heap should take O(n log n) because heapify can take O(log n). But the bottom levels of the tree contain many nodes that require very little work, while only a few top-level nodes can move far downward.

Because of this distribution, the total cost of building the heap from bottom to top is actually O(n).

This is an important exam point: heap construction by bottom-up heapify is O(n), not O(n log n).

Heapify Operation

Heapify restores the heap property for a subtree whose root may violate the heap condition.

For a max-heap:

  1. compare the root with its left and right children,
  2. find the largest among them,
  3. if the root is not largest, swap it with the larger child,
  4. continue heapifying the affected subtree.

Heapify takes O(log n) in the worst case because the element may move down through the height of the heap.

Heap Sort Implementation
import java.util.Arrays;

public class HeapSort {

    static void heapify(int[] arr, int heapSize, int i) {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;

        if (left < heapSize && arr[left] > arr[largest]) {
            largest = left;
        }
        if (right < heapSize && arr[right] > arr[largest]) {
            largest = right;
        }

        if (largest != i) {
            int temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;

            heapify(arr, heapSize, largest);
        }
    }

    static void heapSort(int[] arr) {
        int n = arr.length;

        // Build max-heap.
        for (int i = n / 2 - 1; i >= 0; i--) {
            heapify(arr, n, i);
        }

        // Move current maximum to the end one by one.
        for (int i = n - 1; i > 0; i--) {
            int temp = arr[0];
            arr[0] = arr[i];
            arr[i] = temp;

            heapify(arr, i, 0);
        }
    }

    static class MaxHeap {
        int[] heap;
        int size;

        MaxHeap(int capacity) {
            heap = new int[capacity];
            size = 0;
        }

        void insert(int value) {
            heap[size] = value;
            int i = size++;

            while (i > 0 && heap[(i - 1) / 2] < heap[i]) {
                int temp = heap[i];
                heap[i] = heap[(i - 1) / 2];
                heap[(i - 1) / 2] = temp;
                i = (i - 1) / 2;
            }
        }

        int extractMax() {
            int max = heap[0];
            heap[0] = heap[--size];
            heapify(heap, size, 0);
            return max;
        }
    }

    public static void main(String[] args) {
        int[] arr = {12, 11, 13, 5, 6, 7};
        System.out.println("Before: " + Arrays.toString(arr));
        heapSort(arr);
        System.out.println("After:  " + Arrays.toString(arr));

        MaxHeap pq = new MaxHeap(10);
        pq.insert(3);
        pq.insert(1);
        pq.insert(4);
        pq.insert(1);
        pq.insert(5);

        System.out.print("Max extractions: ");
        while (pq.size > 0) {
            System.out.print(pq.extractMax() + " ");
        }
    }
}

Heap Sort Step by Step

Consider the array [12, 11, 13, 5, 6, 7].

  1. Build max-heap: rearrange the array so the largest value reaches the root. One valid max-heap is [13, 11, 12, 5, 6, 7].
  2. Swap root with last element: move 13 to the final position.
  3. Reduce heap size: now sort only the remaining unsorted prefix.
  4. Heapify the root: restore the max-heap among remaining elements.
  5. Repeat: each pass places one maximum element at the end.

A few steps look like this:

  • [13, 11, 12, 5, 6, 7]
  • swap root and last: [7, 11, 12, 5, 6, 13]
  • heapify remaining heap: [12, 11, 7, 5, 6, 13]
  • swap again: [6, 11, 7, 5, 12, 13]
  • heapify: [11, 6, 7, 5, 12, 13]
  • continue until sorted: [5, 6, 7, 11, 12, 13]

Why Heap Sort Is Not Stable

A sorting algorithm is stable if equal elements keep their original relative order. Heap Sort is not stable because swapping the root with the last element can change the relative order of equal values.

When to Use Heap Sort

Heap Sort is a good choice when:

  • you need guaranteed O(n log n) worst-case performance,
  • you want an in-place sorting algorithm,
  • stability is not required.

It is less attractive when cache performance matters heavily, because heap operations jump around in memory more than algorithms like Quick Sort.

Heap Sort vs Merge Sort vs Quick Sort

Algorithm Best Average Worst Space Stable Main Strength
Quick Sort O(n log n) O(n log n) O(n^2) O(log n) No Usually fastest in practice
Merge Sort O(n log n) O(n log n) O(n log n) O(n) Yes Stable and predictable
Heap Sort O(n log n) O(n log n) O(n log n) O(1) No Worst-case guarantee with in-place sorting

Advantages of Heap Sort

  • Guaranteed O(n log n) in all cases.
  • Works in-place with O(1) extra space.
  • Based on the useful heap data structure, which also supports priority queues.

Limitations of Heap Sort

  • Not stable.
  • Often slower than Quick Sort in real systems because of poor cache locality.
  • Implementation is slightly less intuitive than some simpler sorts.

Common Mistakes

  • Confusing a heap with a fully sorted binary tree.
  • Forgetting that only the root is guaranteed to be the maximum in a max-heap.
  • Thinking build-heap takes O(n log n) when bottom-up build is actually O(n).
  • Using the full array size during heapify after the sorted suffix has already grown.
  • Assuming Heap Sort is stable.

Sorting Algorithms Comparison

Algorithm Best Average Worst Space Stable Notes
Bubble Sort O(n) O(n^2) O(n^2) O(1) Yes Simple but slow
Selection Sort O(n^2) O(n^2) O(n^2) O(1) No Few swaps
Insertion Sort O(n) O(n^2) O(n^2) O(1) Yes Good for small or nearly sorted data
Merge Sort O(n log n) O(n log n) O(n log n) O(n) Yes Stable and guaranteed
Quick Sort O(n log n) O(n log n) O(n^2) O(log n) No Usually fastest in practice
Heap Sort O(n log n) O(n log n) O(n log n) O(1) No Guaranteed and in-place
Counting Sort O(n + k) O(n + k) O(n + k) O(k) Yes For integer keys in a limited range
Radix Sort O(nk) O(nk) O(nk) O(n + k) Yes Non-comparison sorting

Key Takeaways

  • A heap is a complete binary tree usually stored in an array.
  • Heap Sort uses a max-heap to sort in ascending order.
  • Build-heap is O(n), but repeated extraction makes total sorting O(n log n).
  • Heap Sort is in-place and has guaranteed worst-case performance.
  • Heap Sort is not stable and is often slower than Quick Sort in practice.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.