A heap is an array wearing a tree costume: children of index i live at 2i+1 and 2i+2; parent at (i−1)/2. Min at the root — always.
“Repeatedly need the smallest/largest” or “O(1) min + O(log n) updates” → heap
Pattern 1: Insert (sift up)
Append at the first free slot, bubble up while smaller than parent:
// PriorityQueue<Integer> pq = new PriorityQueue<>();
public void insert(int[] heap, int size, int x) {
int i = size;
heap[i] = x;
while (i > 0) {
int p = (i - 1) / 2;
if (heap[i] >= heap[p]) break;
swap(heap, i, p);
i = p;
}
}import heapq
# heapq is a MIN-heap out of the box
heapq.heappush(pq, x)priority_queue<int, vector<int>, greater<int>> pq; // min-heap
pq.push(x); // max-heap by default without greater<>// No built-in heap — tiny binary-heap class
class MinHeap {
push(x) {
this.a.push(x);
let i = this.a.length - 1;
while (i > 0) {
const p = (i - 1) >> 1;
if (this.a[i] >= this.a[p]) break;
[this.a[i], this.a[p]] = [this.a[p], this.a[i]];
i = p;
}
}
}Pattern 2: Extract-Min (sift down)
Watch 4 climb to the root on insert, and 17 sink to a leaf after extraction. Press ▶.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Priority Queue: Insert & Extract
A heap is an array wearing a tree costume: children of index i live at 2i+1 and 2i+2; parent at (i−1)/2. Min at the root — always.
We insert 4 into the min-heap [8,14,10,22,16,12]. The heap is placed at the first free slot (index 6), then bubbles up by swapping with its parent whenever it's smaller. Watch how 4 climbs from index 6 to the root.
1
# insert(x): append, then bubble up
2
append x at index i
3
while i > 0:
4
p = (i - 1) / 2
5
if heap[i] >= heap[p]: break
6
swap(i, p); i = p
1
# extractMin():
2
min = heap[0] # root is always min
3
heap[0] = last element; size--
4
i = 0
5
loop: compare i with children 2i+1, 2i+2
6
swap with the SMALLER child if it's smaller than me
7
else stop
Root is the minimum. Replace it with the last element, then sink it past its smaller child:
public int extractMin(int[] heap, int size) {
int min = heap[0];
heap[0] = heap[size - 1]; // last fills the root hole
siftDown(heap, 0, size - 1);
return min;
}
void siftDown(int[] a, int i, int n) {
while (true) {
int l = 2*i + 1, r = 2*i + 2, s = i;
if (l < n && a[l] < a[s]) s = l;
if (r < n && a[r] < a[s]) s = r;
if (s == i) return;
swap(a, i, s);
i = s;
}
}smallest = heapq.heappop(pq)int smallest = pq.top(); pq.pop();pop() {
const top = this.a[0];
const last = this.a.pop();
if (this.a.length) {
this.a[0] = last;
let i = 0;
for (;;) {
const l = 2 * i + 1, r = l + 1;
let s = i;
if (l < this.a.length && this.a[l] < this.a[s]) s = l;
if (r < this.a.length && this.a[r] < this.a[s]) s = r;
if (s === i) break;
[this.a[i], this.a[s]] = [this.a[s], this.a[i]];
i = s;
}
}
return top;
}The array IS the tree — index math replaces pointers entirely.
Common Mistakes
- Using a max-heap when you needed min (
greater<>in C++, negation in Python). - Sifting down via the bigger child in a min-heap — always pick the smaller child.
- Forgetting
size--before/after moving the last element into the root. - Off-by-one on child indexes: they are
2i+1,2i+2— never2i.
Complexity
| Operation | Time | Space |
|---|---|---|
| peek | O(1) | O(1) |
| push | O(log n) | O(1) |
| pop | O(log n) | O(1) |
| build (n items) | O(n) | O(n) |
Premium Content
Unlock Priority Queue and all premium lessons with a subscription.
From ₹199.99/year — See plans