1 of 6
Welcome! Learn how heaps work โ the data structure behind priority queues, scheduling, and finding min/max efficiently!
A Heap is a special tree-based data structure where the parent is always smaller (min-heap) or larger (max-heap) than its children.
Real-World Examples:
Key Idea: Always access the smallest (or largest) element in O(1) time!
A heap is a complete binary tree stored as a list/array!
1 Index: 0
/ \
3 5 Index: 1, 2
/ \ / \
7 4 8 6 Index: 3, 4, 5, 6
As a list: [1, 3, 5, 7, 4, 8, 6]
Parent-Child Relationships (0-indexed):
parent(i) = (i - 1) // 2 left_child(i) = 2 * i + 1 right_child(i) = 2 * i + 2
Example:
heap = [1, 3, 5, 7, 4, 8, 6] # Node at index 1 (value 3): # Parent: (1-1)//2 = 0 โ value 1 โ (1 < 3) # Left child: 2*1+1 = 3 โ value 7 # Right child: 2*1+2 = 4 โ value 4
๐ก Try the interactive animation on this page! Watch how insert and extract work step by step.
When inserting, add to the end and bubble up to maintain heap property:
import heapq heap = [1, 3, 5, 7, 4] heapq.heappush(heap, 2) print(heap) # [1, 3, 2, 7, 4, 5] # Step by step: # 1. Add 2 at end: [1, 3, 5, 7, 4, 2] # 2. Compare with parent (5): 2 < 5, swap! # [1, 3, 2, 7, 4, 5] # 3. Compare with parent (1): 2 > 1, stop!
When removing the min, replace root with last element and bubble down:
import heapq heap = [1, 3, 2, 7, 4, 5] smallest = heapq.heappop(heap) print(smallest) # 1 print(heap) # [2, 3, 5, 7, 4] # Step by step: # 1. Remove root (1), move last (5) to root: # [5, 3, 2, 7, 4] # 2. Compare with children (3, 2): 2 is smallest, swap! # [2, 3, 5, 7, 4] # 3. No more children, stop!
heapq ModulePython has a built-in min-heap module!
import heapq # Create a heap from a list nums = [5, 3, 8, 1, 4] heapq.heapify(nums) print(nums) # [1, 3, 8, 5, 4] # Push (insert) heapq.heappush(nums, 2) print(nums) # [1, 3, 2, 5, 4, 8] # Pop (extract min) smallest = heapq.heappop(nums) print(smallest) # 1 # Peek at min without removing print(nums[0]) # 2 (just access index 0!) # Push and pop in one step result = heapq.heappushpop(nums, 6) print(result) # 2 (pushed 6, popped smallest)
Python only has min-heap. For max-heap, negate the values!
import heapq # Max-heap using negation max_heap = [] values = [3, 1, 5, 2, 4] for val in values: heapq.heappush(max_heap, -val) # Negate! # Get max value largest = -heapq.heappop(max_heap) # Negate back! print(largest) # 5
Watch insert, extract, and build heap in action!
Min-Heap: Parent โค Children
Parent
โ(i โ 1) / 2โLeft Child
2 ร i + 1Right Child
2 ร i + 2๐ Click any node in the tree to see the formulas in action
Array Representation:
Start from index โn/2โ โ 1 = 2 and bubble down each node going left to index 0. Leaves (indices 3โ6) are already valid heaps โ skip them!
| Operation | Time | Space | Why |
|---|---|---|---|
| Insert | O(log n) | O(1) | Bubble up through at most log n levels |
| Extract Min | O(log n) | O(1) | Bubble down through at most log n levels |
| Peek (min) | O(1) | O(1) | Min is always at index 0 (root) |
| Heapify (build) | O(n) | O(1) | Bottom-up โ most nodes are leaves and don't move |
| Insert n items | O(n log n) | O(n) | Each of n inserts costs O(log n) |
| Search | O(n) | O(1) | Heap is not sorted โ must check every element |
Heapify works bottom-up: it calls bubble_down from the last non-leaf to the root. Most nodes are near the bottom of the tree and move very little:
Leaves (bottom)
n/2 nodes
0 moves
Level above
n/4 nodes
โค 1 move
Next level
n/8 nodes
โค 2 moves
Root (top)
1 node
โค log n moves
Total work: n/4 ยท 1 + n/8 ยท 2 + n/16 ยท 3 + ... โ n (geometric series). Half the nodes do zero work, a quarter do one swap โ it adds up to O(n), not O(n log n).
โ Standard library: heapq, collections, itertools, math, random, functools, datetime, bisect
โ Functions, classes, recursion, print()
โ No file system, subprocess, OS access, or network requests
โ No pip install (all supported modules are pre-loaded)
โฑ๏ธ 5 second execution time limit