Overview of Heap Sort
Heap sort is a powerful comparison-based sorting algorithm that leverages the properties of a binary heap data structure. It offers a time complexity of O(n log n), making it suitable for sorting large datasets. Unlike some other sorting algorithms, heap sort is in-place and has consistent performance across best, average, and worst-case scenarios. However, its not a stable sort, meaning that the relative order of equal elements may not be preserved.
Understanding the Binary Heap
Heap sort works by first converting the input array into a max-heap — a complete binary tree where the parent node is always greater than or equal to its children. Once the heap is built, the largest element (the root) is repeatedly extracted and placed at the end of the array, and the remaining elements are restructured into a heap again.
Core Implementation in C
#include <stdio.h>
// Function to swap two integer values
void exchange(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// Function to maintain heap properties
void restructureHeap(int array[], int heapSize, int index) {
int largest = index;
int leftChild = 2 * index + 1;
int rightChild = 2 * index + 2;
if (leftChild < heapSize && array[leftChild] > array[largest]) {
largest = leftChild;
}
if (rightChild < heapSize && array[rightChild] > array[largest]) {
largest = rightChild;
}
if (largest != index) {
exchange(&array[index], &array[largest]);
restructureHeap(array, heapSize, largest);
}
}
// Main heap sort function
void performHeapSort(int array[], int length) {
// Build max heap
for (int i = length / 2 - 1; i >= 0; i--) {
restructureHeap(array, length, i);
}
// Extract elements from heap one by one
for (int i = length - 1; i >= 0; i--) {
exchange(&array[0], &array[i]);
restructureHeap(array, i, 0);
}
}
// Utility to display array contents
void showArray(int array[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", array[i]);
}
printf("\n");
}
// Test entry point
int main() {
int data[] = {12, 11, 13, 5, 6, 7};
int size = sizeof(data) / sizeof(data[0]);
printf("Original array:\n");
showArray(data, size);
performHeapSort(data, size);
printf("Sorted array:\n");
showArray(data, size);
return 0;
}
Explanation of Key Functions
exchange: Swaps two integer values using pointers.restructureHeap: Ensures the subtree rooted at a given index satisfies the max-heap property by comparing and swapping nodes as necessary.performHeapSort: Constructs the initial max-heap and repeatedly extracts the maximum element to build the sorted array.showArray: Outputs the array elements for verification.main: Demonstrates the sorting process with a sample dataset.
Optimization Techniques
While the standard implementation is efficient, certain optimizations can further enhance performance:
- Iterative Heapify: Replace the recursive heapify function with an iterative version to reduce function call overhead.
void restructureHeap(int array[], int heapSize, int index) {
int largest;
int left, right;
while (index < heapSize) {
largest = index;
left = 2 * index + 1;
right = 2 * index + 2;
if (left < heapSize && array[left] > array[largest]) {
largest = left;
}
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
if (largest != index) {
exchange(&array[index], &array[largest]);
index = largest;
} else {
break;
}
}
}
- Minimize Swaps: Avoid unnecessary element swaps by deferring them until necessary during heap restructuring.
Performance Characteristics
Heap sort consistently performms in O(n log n) time regardless of input distribution. Building the heap initially takes O(n) time, while each of the n extraction steps takes O(log n). The algorithm operates in-place with O(1) additional space, making it suitable for memory-constrained environments.
Practical Use Cases
Heap sort is particularly useful in the following scenarios:
- Sorting large arrays where memory usage is a concern.
- Applications requiring predictable O(n log n) performance.
- Implementing priority queues where efficient extraction of maximum or minimum elements is needed.