Data Structure
Max Heap
“The VIP Club”
History
The Heap was introduced by J.W.J. Williams in 1964 as a data structure specifically designed for the Heapsort algorithm.
It is a "Priority Queue" implementation. It doesn't care about sorting everything perfectly; it only cares that the most important element (the max) is accessible instantly. It's the bouncer at the club who only lets the biggest celebrity stand at the front.
Core Property
The Heap Property
For any given node , the value of is greater than or equal to the values of its children. This means the largest element is always at the Root.
How It Works
Heaps are usually implemented as Arrays, not node objects. We use math to simulate the tree structure.
- Parent index:
- Left Child:
- Right Child:
The Operations
- Insert (Bubble Up): Add to the end of the array, then swap with parent until the property is restored.
- Extract Max (Bubble Down): Take the root (max), move the last element to the root, then swap it down with the larger child until it settles.
Heaps are not for searching. Finding an arbitrary element requires scanning the array.
We add to the bottom and swim up. The height is always $log n$.
Specifically for deleting the Root (Extract Max). Deleting an arbitrary node is harder.
Extremely efficient. It's just a raw array with zero pointer overhead.
Code Walkthrough
Complete data structure implementations in multiple programming languages. Select a language to view idiomatic code.
1class MaxHeap:2 """Array-based Max Heap implementation.34 Parent index: (i - 1) // 25 Left child index: 2 * i + 16 Right child index: 2 * i + 27 """8 def __init__(self):9 self.heap: list[int] = []1011 def _parent(self, i: int) -> int:12 return (i - 1) // 21314 def _left_child(self, i: int) -> int:15 return 2 * i + 11617 def _right_child(self, i: int) -> int:18 return 2 * i + 21920 def _swap(self, i: int, j: int) -> None:21 self.heap[i], self.heap[j] = self.heap[j], self.heap[i]2223 def insert(self, val: int) -> None:24 """Insert value and bubble up to maintain heap property."""25 self.heap.append(val)26 self._bubble_up(len(self.heap) - 1)2728 def _bubble_up(self, i: int) -> None:29 """Move element up until heap property is satisfied."""30 while i > 0:31 parent = self._parent(i)32 if self.heap[i] <= self.heap[parent]:33 break34 self._swap(i, parent)35 i = parent3637 def extract_max(self) -> int | None:38 """Remove and return the maximum element."""39 if not self.heap:40 return None4142 max_val = self.heap[0]43 last = self.heap.pop()4445 if self.heap:46 self.heap[0] = last47 self._sink_down(0)4849 return max_val5051 def _sink_down(self, i: int) -> None:52 """Move element down until heap property is satisfied."""53 n = len(self.heap)54 while True:55 largest = i56 left = self._left_child(i)57 right = self._right_child(i)5859 if left < n and self.heap[left] > self.heap[largest]:60 largest = left61 if right < n and self.heap[right] > self.heap[largest]:62 largest = right6364 if largest == i:65 break6667 self._swap(i, largest)68 i = largest6970 def peek(self) -> int | None:71 """Return the maximum element without removing it."""72 return self.heap[0] if self.heap else NoneReal World Use Cases
- 1Priority Queues (Job scheduling, Bandwidth management)
- 2Heapsort algorithm
- 3Graph algorithms (Dijkstra, Prim's)
- 4Finding the 'K' largest elements in a stream
Key Insights
- O(1) access to the maximum element.
- It is NOT a sorted structure. It is a 'partially ordered' structure.
- Array implementation gives it amazing cache locality.
- It is a Complete Binary Tree (perfectly balanced except the bottom row).
When to Use
Use a Max Heap when you need constant-time access to the 'highest priority' item, or when implementing a Priority Queue.
When NOT to Use
Do not use a Heap if you need to search for arbitrary values or if you need to traverse the data in sorted order.
Watch Out
Confusing it with a BST. In a Heap, the Left child could be larger than the Right child. The only rule is Parent > Children.