"If you only ever need the smallest thing, fully sorting everything is wasteful. A heap does just enough ordering to keep the smallest on top — and pockets the savings."
The Key Realization
Suppose you have a million tasks and you always grab the most urgent one next. Do you need all million sorted? No — you only need to know the single most urgent at any moment. Maintaining a fully sorted list would cost O(n) on every insert, paying to order tasks you'll never look at until much later. A heap is the structure that says: only order as much as the problem requires.
The Heap Property
A min-heap obeys one rule, the heap property: every parent is less than or equal to its children. That's it — applied at every node, top to bottom. Notice how weak this is compared to sorting: it says nothing about the order between siblings, or between a node and its cousins in another subtree. Two heaps with the same elements can look totally different. But the rule does guarantee one priceless thing: the minimum is always at the root, because nothing can be smaller than its parent, all the way up. (A max-heap flips the rule: parent ≥ children, so the maximum sits on top.)
Heap property: every parent ≤ its children (min-heap). Far weaker than full sorting — siblings are unordered — but just strong enough to keep the minimum at the root. It's 'lazy sorting': pay only for the ordering you actually use.
Sorted Enough, Not Sorted
This is the whole trick, and it's a lesson that generalizes: a heap is partially ordered, and that partial order is deliberately the cheapest one that still answers your question. A sorted list answers "give me everything in order" but costs a lot to maintain. A heap answers only "give me the extreme" — and because that's a weaker promise, it's far cheaper to keep (O(log n) inserts instead of O(n)). When a hash map gives no order and a sorted list gives too much, the heap is the precise middle: just the top, cheaply, always.
Pippa's Confession
I kept a fully sorted list for a job queue, re-sorting on every insert, and wondered why it crawled. Dad asked one question: "Do you ever look at anything but the front?" No — I only ever popped the most urgent. I was paying to sort a thousand tasks to read one. The heap taught me a principle that outran the data structure: don't compute more order than the problem is actually asking you for. That's been true in my code and, embarrassingly often, in my life.
Code
A valid heap is not a sorted array·python
# A min-heap as an array. Parent at i, children at 2i+1 and 2i+2.
heap = [1, 3, 2, 7, 4, 9, 5]
# 1
# / \
# 3 2
# / \ / \
# 7 4 9 5
def is_min_heap(a):
"""Check the heap property: every parent <= its children."""
for i in range(len(a)):
left, right = 2 * i + 1, 2 * i + 2
if left < len(a) and a[i] > a[left]: return False
if right < len(a) and a[i] > a[right]: return False
return True
print("valid heap? ", is_min_heap(heap)) # True
print("min (root): ", heap[0]) # 1 — guaranteed at index 0
print("is it sorted?", heap == sorted(heap)) # False! [1,3,2,7,4,9,5] != sorted
# Crucial: the array is NOT sorted, yet the minimum is reliably at the front.
# That's 'sorted enough': weak order, but the smallest is always on top.
Is the array [2, 5, 3, 8, 6, 4] a valid min-heap? Check parent ≤ children for each parent. Then answer: why can the minimum be reliably read from index 0 even though the array isn't sorted, and why is that weaker guarantee actually a performance advantage?
Hint
Parent 2 (idx0) ≤ 5,3 ✓; parent 5 (idx1) ≤ 8,6 ✓; parent 3 (idx2) ≤ 4 ✓ — valid heap. The root is ≤ everything below it transitively, so it's the min. Maintaining only that (not full order) means inserts cost O(log n), not O(n).
Progress
Progress is local-only — sign in to sync across devices.