Report Content
×Heaps in DSA: Priority Queues & Heap Algorithms
Master heap operations, heap sort, and priority queue implementations. This tutorial covers min/max heaps, heapify algorithms, and real-world applications with coding examples.
Heap Usage in Systems (2023)
1. Heap Fundamentals
Min-Heap
Definition
Min-Heap is a complete binary tree where the value of each node is less than or equal to the values of its children. The smallest element is always at the root, making it ideal for priority queues where the highest priority is the smallest value.
How It Works
Insert (Bubble Up)
- Add new element at the end of the heap array
- Compare with parent; swap if smaller
- Repeat until heap property is restored
Extract Min (Sink Down)
- Remove root (minimum element)
- Move last element to root
- Compare with children; swap with smallest child
- Repeat until heap property is restored
Array Representation
- Parent: (i-1)/2
- Left Child: 2i+1
- Right Child: 2i+2
class MinHeap:
def __init__(self):
self.heap = []
def insert(self, value):
self.heap.append(value)
self._bubble_up(len(self.heap) - 1)
def extract_min(self):
if not self.heap:
raise Exception("Heap is empty")
min_val = self.heap[0]
last = self.heap.pop()
if self.heap:
self.heap[0] = last
self._sink_down(0)
return min_val
def _bubble_up(self, index):
while index > 0:
parent = (index - 1) // 2
if self.heap[parent] <= self.heap[index]:
break
self.heap[parent], self.heap[index] = self.heap[index], self.heap[parent]
index = parent
def _sink_down(self, index):
smallest = index
left = 2 * index + 1
right = 2 * index + 2
if left < len(self.heap) and self.heap[left] < self.heap[smallest]:
smallest = left
if right < len(self.heap) and self.heap[right] < self.heap[smallest]:
smallest = right
if smallest != index:
self.heap[index], self.heap[smallest] = self.heap[smallest], self.heap[index]
self._sink_down(smallest)
def peek(self):
return self.heap[0] if self.heap else None
def size(self):
return len(self.heap)
Complexity: Insert O(log n), Extract O(log n), Peek O(1)
Use When: Need quick access to minimum element
Max-Heap
Definition
Max-Heap is a complete binary tree where the value of each node is greater than or equal to the values of its children. The largest element is always at the root, making it ideal for problems requiring the maximum element.
How It Works
Insert (Bubble Up)
- Add new element at the end
- Compare with parent; swap if larger
- Repeat until heap property restored
Extract Max (Sink Down)
- Remove root (maximum element)
- Move last element to root
- Compare with children; swap with largest child
- Repeat until heap property restored
class MaxHeap:
def __init__(self):
self.heap = []
def insert(self, value):
self.heap.append(value)
self._bubble_up(len(self.heap) - 1)
def extract_max(self):
if not self.heap:
raise Exception("Heap is empty")
max_val = self.heap[0]
last = self.heap.pop()
if self.heap:
self.heap[0] = last
self._sink_down(0)
return max_val
def _bubble_up(self, index):
while index > 0:
parent = (index - 1) // 2
if self.heap[parent] >= self.heap[index]:
break
self.heap[parent], self.heap[index] = self.heap[index], self.heap[parent]
index = parent
def _sink_down(self, index):
largest = index
left = 2 * index + 1
right = 2 * index + 2
if left < len(self.heap) and self.heap[left] > self.heap[largest]:
largest = left
if right < len(self.heap) and self.heap[right] > self.heap[largest]:
largest = right
if largest != index:
self.heap[index], self.heap[largest] = self.heap[largest], self.heap[index]
self._sink_down(largest)
def peek(self):
return self.heap[0] if self.heap else None
2. Heap Operations & Algorithms
Heap Sort
Definition
Heap Sort is a comparison-based sorting algorithm that uses a binary heap data structure. It divides the array into sorted and unsorted regions and repeatedly extracts the maximum/minimum element from the heap.
How It Works
Build Max Heap
- Start from last non-leaf node
- Heapify each node to satisfy heap property
- Result: Largest element at root
Extract & Swap
- Swap root (largest) with last element
- Reduce heap size by 1
- Heapify the reduced heap
Repeat
- Continue until heap size becomes 1
- Array becomes sorted in ascending order
def heap_sort(arr):
n = len(arr)
# Build max heap
for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)
# Extract elements one by one
for i in range(n - 1, 0, -1):
arr[0], arr[i] = arr[i], arr[0] # Swap
heapify(arr, i, 0)
return arr
def heapify(arr, n, i):
largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and arr[left] > arr[largest]:
largest = left
if right < n and arr[right] > arr[largest]:
largest = right
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
Complexity: O(n log n) time, O(1) space
Use When: In-place sorting with guaranteed O(n log n)
Top K Elements
Definition
Top K Elements problem finds the K largest or smallest elements in an array using a min-heap or max-heap. This approach is optimal for large datasets.
How It Works
Initialize Min-Heap
- Create min-heap of size K
- Insert first K elements
Process Remaining
- For each element, compare with heap root
- If larger than root, remove root and insert element
Extract Result
- Heap contains K largest elements
- Elements remain in heap order
import heapq
def top_k_elements(nums, k):
min_heap = []
for num in nums:
heapq.heappush(min_heap, num)
if len(min_heap) > k:
heapq.heappop(min_heap)
return min_heap
# For Kth largest element
def kth_largest(nums, k):
min_heap = []
for num in nums:
heapq.heappush(min_heap, num)
if len(min_heap) > k:
heapq.heappop(min_heap)
return min_heap[0]
Complexity: O(n log k) time, O(k) space
Use When: Finding top/largest K elements
3. Heapify & Heap Construction
Heapify (Build Heap)
Definition
Heapify is the process of converting an arbitrary array into a heap in O(n) time. It works by applying the sink-down operation on non-leaf nodes from bottom to top.
How It Works
Start from last non-leaf
- Index = (n/2) - 1
- All leaf nodes are already valid heaps
Apply sink-down
- For each node, ensure it's >= children
- Swap if needed and recurse down
Move upward
- Continue for all indices down to 0
- Result: Complete heap structure
def heapify(arr, n, i):
largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and arr[left] > arr[largest]:
largest = left
if right < n and arr[right] > arr[largest]:
largest = right
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
def build_heap(arr):
n = len(arr)
# Start from last non-leaf node
for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)
return arr
Complexity: O(n) time, O(log n) recursion stack
Use When: Converting array to heap efficiently
4. Real-World Applications
Priority Queue (Task Scheduler)
Task Scheduling: Operating systems use heaps to schedule processes by priority
import heapq
class TaskScheduler:
def __init__(self):
self.heap = [] # (priority, task)
def add_task(self, task, priority):
heapq.heappush(self.heap, (priority, task))
def execute_task(self):
if self.heap:
priority, task = heapq.heappop(self.heap)
return task
return None
Dijkstra's Shortest Path
Graph Algorithms: Heaps optimize distance calculations
import heapq
def dijkstra(graph, start):
distances = {node: float('inf') for node in graph}
distances[start] = 0
pq = [(0, start)]
while pq:
current_dist, node = heapq.heappop(pq)
if current_dist > distances[node]:
continue
for neighbor, weight in graph[node]:
distance = current_dist + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
return distances
Median Maintenance
Two-Heap Approach: Track median in a data stream
import heapq
class MedianFinder:
def __init__(self):
self.max_heap = [] # store smaller half (negated for max-heap)
self.min_heap = [] # store larger half
def add_num(self, num):
heapq.heappush(self.max_heap, -num)
heapq.heappush(self.min_heap, -heapq.heappop(self.max_heap))
if len(self.min_heap) > len(self.max_heap):
heapq.heappush(self.max_heap, -heapq.heappop(self.min_heap))
def find_median(self):
if len(self.max_heap) > len(self.min_heap):
return -self.max_heap[0]
return (-self.max_heap[0] + self.min_heap[0]) / 2
Heap Problem-Solving Cheat Sheet
| Problem Type | Approach | Time Complexity |
|---|---|---|
| Kth Largest Element | Min-heap of size K | O(n log k) |
| Merge K Sorted Arrays | Min-heap with pointers | O(n log k) |
| Sliding Window Median | Two heaps (min + max) | O(n log k) |
| Huffman Coding | Min-heap for tree construction | O(n log n) |
| Dijkstra's Algorithm | Min-heap for distances | O(E log V) |
Heap Problem-Solving Checklist
DSA Expert Insight: Heap problems appear in 30% of technical interviews, especially in priority queue and top-K element scenarios. Mastering both basic operations and specialized heap variants is key to efficient problem-solving. The two-heap pattern is particularly powerful for streaming median problems.
You need to be logged in to participate in this discussion.