- What is Heap Sort algorithm and how it works
- How to implement Heap Sort in C programming
- What is a Max Heap and how to build it
- How to use the heapify function
- Time and space complexity analysis
Introduction to Heap Sort
Heap Sort is a comparison-based sorting algorithm that uses a binary heap data structure. It works by first building a max heap from the input array, then repeatedly extracting the largest element from the heap and placing it at the end of the array.
A binary heap is a complete binary tree where each node is greater than or equal to its children (max heap) or less than or equal to its children (min heap). Heap Sort uses a max heap to sort in ascending order.
Key characteristics of Heap Sort:
- In-place algorithm: Sorts the array without using extra memory
- Not stable: Does not preserve the relative order of equal elements
- Guaranteed O(n log n) performance: Works consistently well
- Useful for priority queues: Efficient for finding largest/smallest elements
š” How it works: Heap Sort builds a max heap from the array, then repeatedly swaps the root (largest element) with the last element, reduces the heap size, and heapifies the new root.
C Program for Heap Sort
#include <stdio.h>
// Function to swap two elements
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// Function to heapify a subtree rooted at index i
// n is the size of the heap
void heapify(int arr[], int n, int i) {
int largest = i; // Initialize largest as root
int left = 2 * i + 1; // Left child index
int right = 2 * i + 2; // Right child index
// If left child is larger than root
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
// If right child is larger 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) {
swap(&arr[i], &arr[largest]);
// Recursively heapify the affected subtree
heapify(arr, n, largest);
}
}
// Main function to perform heap sort
void heapSort(int arr[], int n) {
// Build max heap (rearrange array)
// Start from the last non-leaf node
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// One by one extract elements from heap
for (int i = n - 1; i > 0; i--) {
// Move current root to end
swap(&arr[0], &arr[i]);
// Call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
// Function to print the array
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// Driver program to test the heap sort
int main() {
int arr[] = {12, 11, 13, 5, 6, 7, 1, 9, 3, 10};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Original array: ");
printArray(arr, n);
heapSort(arr, n);
printf("Sorted array: ");
printArray(arr, n);
return 0;
}
Sample Output
Original array: 12 11 13 5 6 7 1 9 3 10 Sorted array: 1 3 5 6 7 9 10 11 12 13
Another Example:
Original array: 45 23 78 12 56 34 89 10 67 90 Sorted array: 10 12 23 34 45 56 67 78 89 90
Program Explanation
Let's break down the code step by step:
- Include Header File:
#include <stdio.h>includes the standard input/output library. - Swap Function:
swap()exchanges two integer values using a temporary variable. - Heapify Function:
- Takes an array, heap size
n, and indexi - Finds the largest among root, left child, and right child
- If root is not largest, swaps and recursively heapifies the affected subtree
- This maintains the max heap property
- Takes an array, heap size
- HeapSort Function:
- Step 1 - Build Max Heap: Starting from the last non-leaf node (
n/2 - 1) up to root, call heapify - Step 2 - Extract Elements: Swap root (largest) with last element, reduce heap size, heapify the new root
- Repeat until all elements are sorted
- Step 1 - Build Max Heap: Starting from the last non-leaf node (
- PrintArray Function: Displays all elements of the array.
- Main Function:
- Creates an unsorted array
- Displays the original array
- Calls
heapSort()to sort - Displays the sorted array
š Note: The heapify function is called recursively. Each call has O(log n) time complexity, and it's called O(n) times, giving us the overall O(n log n) performance.
Step-by-Step Approach
| Step | Action | Explanation |
|---|---|---|
| 1 | Build Max Heap | Convert array into a max heap structure |
| 2 | Extract Root | Swap root with last element |
| 3 | Heapify | Restore heap property for reduced heap |
| 4 | Repeat | Continue until all elements are sorted |
Algorithm for Heap Sort
- Build Max Heap:
- For
i = n/2 - 1down to0:- Call
heapify(arr, n, i)
- Call
- For
- Sort:
- For
i = n - 1down to1:- Swap
arr[0]andarr[i] - Call
heapify(arr, i, 0)
- Swap
- For
- Done: Array is now sorted in ascending order
Time & Space Complexity
| Complexity | Best Case | Average Case | Worst Case |
|---|---|---|---|
| Time | O(n log n) | O(n log n) | O(n log n) |
| Space | O(1) - In-place sorting | ||
š Key Points:
- Heap Sort has guaranteed O(n log n) time complexity in all cases
- It is an in-place algorithm (O(1) extra space)
- Not stable - equal elements may not retain their original order
- Faster than merge sort for large datasets due to in-place nature
š» Practice Exercise
Challenge 1: Modify the program to sort the array in descending order using Heap Sort.
Challenge 2: Write a program to find the kth largest element in an array using Heap Sort.
Challenge 3: Implement Heap Sort on an array of strings (lexicographical order).
š Click to Show Solution for Challenge 1
// To sort in descending order, use MIN HEAP instead of MAX HEAP
// Change the comparison in heapify function:
if (left < n && arr[left] < arr[smallest]) {
smallest = left;
}
if (right < n && arr[right] < arr[smallest]) {
smallest = right;
}
// This creates a min heap, resulting in descending order
// after extraction.
š Click to Show Solution for Challenge 2
int findKthLargest(int arr[], int n, int k) {
// Build max heap
for (int i = n/2 - 1; i >= 0; i--)
heapify(arr, n, i);
// Extract k-1 elements
for (int i = n-1; i > n-k; i--) {
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
return arr[0]; // kth largest
}
Frequently Asked Questions
1. What is the difference between Heap Sort and other sorting algorithms?
Heap Sort has guaranteed O(n log n) performance, while Quick Sort has O(n log n) average but O(n²) worst case. Merge Sort has O(n log n) but requires O(n) extra space. Heap Sort is in-place, making it memory efficient.
2. Why do we build a max heap for ascending order?
A max heap ensures the largest element is at the root. By repeatedly removing the root (largest element) and placing it at the end, we build the sorted array from largest to smallest, resulting in ascending order.
3. Is Heap Sort stable?
No, Heap Sort is not stable. Equal elements may not retain their original relative order because the sorting process doesn't consider the original positions of equal elements.
4. When should I use Heap Sort?
Heap Sort is ideal when:
- You need guaranteed O(n log n) performance
- Memory usage is a concern (in-place sorting)
- You're implementing priority queues
- You need to find kth largest/smallest elements
5. What is the space complexity of Heap Sort?
Heap Sort has O(1) space complexity (in-place) because it only uses a constant amount of extra memory for variables like loop counters and temporary storage during swaps.
š” Tip: Heap Sort is an excellent choice when you need consistent performance regardless of input data distribution.