Chapter 9: Heaps & Priority Queues
Master heap data structures and priority queues for efficient element retrieval. Learn heap operations, Python's heapq module, and solve classic interview problems including k closest points, merging sorted lists, kth largest element, string reorganization, and running median.
Chapter Overview
A heap is a specialized tree-based data structure that satisfies the heap property: in a min-heap, every parent is smaller than or equal to its children; in a max-heap, every parent is larger than or equal to its children. This guarantees the minimum (or maximum) element is always at the root, accessible in time.
Heaps power priority queues --- abstract data structures where the highest-priority element is always served first, regardless of insertion order. Operations like push and pop run in time, making heaps ideal for problems that repeatedly ask for the smallest or largest element from a dynamic collection.
This chapter covers:
- Heap Fundamentals: How heaps work internally, heapify, and Python's heapq
- K Closest Points: Using a heap to find the k nearest points to the origin
- Merge K Sorted Lists: Efficiently merging multiple sorted sequences with a heap
- Kth Largest Element: Maintaining a min-heap of size k for streaming data
- Reorganize String: Greedy character placement using a max-heap
- Find Median from Data Stream: The elegant two-heap technique for running median
Chapter Roadmap
Click any topic to jump in
Heap Fundamentals
Complete binary tree with the heap property — $O(\log n)$ push/pop via sift-up and sift-down.
Bounded-size heaps
K Closest Points
Find the $k$ nearest neighbors to the origin — max-heap of size $k$ keeps it $O(n \log k)$.
Merge K Sorted Lists
K-way merge with a min-heap — always pop the smallest next element across all lists.
Kth Largest Element
Maintain a running min-heap of size $k$ — the root is always the answer.
Reorganize String
Greedy max-heap on character counts — interleave the most frequent letters to avoid adjacency.
Median from Stream
Two heaps split the data in half — $O(\log n)$ insert, $O(1)$ median query.
A binary heap is a complete binary tree stored as an array. The heap property ensures that the root always holds the extreme value --- the minimum in a min-heap or the maximum in a max-heap. Because the tree is complete, we can map parent-child relationships to array indices without using pointers.
Python's heapq module provides a min-heap implementation built on top of a regular list. Understanding how heaps work internally --- heapify up on insertion, heapify down on extraction --- is essential for solving priority queue problems efficiently. The push and pop operations make heaps dramatically faster than sorting after every insertion.
In this topic
Min-Heap and Max-Heap Structure
A min-heap ensures that every parent node is less than or equal to its children. The smallest element sits at the root (index 0). A max-heap is the reverse --- every parent is greater than or equal to its children, so the largest element is at the root.
Since a heap is a complete binary tree stored as an array, the parent-child relationships follow simple index formulas:
- Parent of node at index :
- Left child:
- Right child:
Push (insert): Add to the end, then sift up by swapping with the parent until the heap property is restored --- . Pop (extract min/max): Swap root with the last element, remove it, then sift down by swapping with the smaller (min-heap) or larger (max-heap) child --- . Peek: Return the root --- .
A binary heap is a complete binary tree where every parent satisfies the heap property: in a min-heap, ; in a max-heap, . Stored as an array, the children of index are at and , and the parent is at . Completeness means height is , so insert (bubble up) and extract-root (sift down) are both . Peek at the root is . A heap of elements uses exactly space with no pointers.
Insert elements [5, 3, 8, 1, 4] into a min-heap one by one. Show the heap state after each insertion.
Heapify and Python heapq
Heapify converts an arbitrary list into a valid heap in time --- faster than inserting elements one by one (). The algorithm starts from the last non-leaf node and sifts down each node. Because most nodes are near the bottom (where sift-down is cheap), the total work is linear.
Python's heapq module provides a min-heap API:
- heapq.heappush(heap, val) --- push a value,
- heapq.heappop(heap) --- pop the smallest,
- heapq.heapify(lst) --- convert list to heap in-place,
- heapq.heappushpop(heap, val) --- push then pop, optimized to
- heapq.nsmallest(k, iterable) and heapq.nlargest(k, iterable) --- find k extreme values
For a max-heap in Python, negate values before pushing and negate again after popping.
Python's heapq module implements a min-heap on a regular list. heapq.heapify(arr) converts an arbitrary list into a heap in — not — by sifting down from the last non-leaf upward; the proof uses a telescoping sum . For a max-heap, negate values (heappush(heap, -x)). heappush and heappop are ; heapq.nlargest(k, arr) uses a size- heap for total.
Given the list [9, 4, 7, 1, 3, 6], show the result of heapify and demonstrate push/pop.