Heap & Priority Queue
A complete binary tree satisfying the heap property, enabling efficient min/max extraction.
The Mathematics
Heap property, array representation, and build-heap analysis
Heap Property
A min-heap is a complete binary tree where every node is smaller than or equal to its children:
This guarantees — the root is always the minimum.
Array Representation
A complete binary tree maps perfectly to an array using index arithmetic:
Parent of node :
Left child:
Right child:
No pointers needed — the tree structure is implicit in the array indices.
Key Operations
Sift Down: If a node violates the heap property, swap it with its smallest child and repeat. Takes .
Build Heap: Call sift-down from the last non-leaf () up to the root.
Extract Min: Remove root, replace with last element, sift down. Takes .
Build Heap: O(n), Not O(n log n)
Surprisingly, building a heap takes , not . Most nodes are near the leaves and sift down only a few levels:
There are leaves (sift 0), nodes at height 1 (sift 1), etc. The sum converges to .
See It Work
Building a min-heap from [4, 10, 3, 5, 1, 8, 2] then extracting min
Array Representation
Start with unordered array. Build a min-heap by sifting down from the last non-leaf node upward.
The Code
Mapping heap operations to Python with sift-down
Mathematical Formulation
Build heap bottom-up from last non-leaf to root
In array representation, children are at indices 2i+1 and 2i+2
If parent is larger than smallest child, swap to restore heap
Root of min-heap is always the minimum element
Replace root with last element and sift down — O(log n)
Python Implementation
def build_min_heap(A):
n = len(A)
for i in range(n // 2 - 1, -1, -1):
sift_down(A, i, n) # Heapify subtree
def sift_down(A, i, n):
smallest = i
left, right = 2*i + 1, 2*i + 2
if left < n and A[left] < A[smallest]:
smallest = left # Left is smaller
if right < n and A[right] < A[smallest]:
smallest = right # Right is smaller
if smallest != i:
A[i], A[smallest] = A[smallest], A[i]
sift_down(A, smallest, n) # Recurse down
def extract_min(A):
min_val = A[0] # Root is min
A[0] = A[-1] # Move last to root
A.pop()
sift_down(A, 0, len(A)) # Restore heap
return min_val