Watch it run
Play it or step through. Every step says what just happened.
const heap = [];function push(x) { heap.push(x); let i = heap.length - 1; while (i > 0) { const parent = (i - 1) >> 1; if (heap[parent] <= heap[i]) break; [heap[parent], heap[i]] = [heap[i], heap[parent]]; i = parent; }}for (const x of [5, 3, 8, 1]) push(x);console.log(heap.join(" "));Still to push
Heap array (index 0 first)
Children of index i live at 2i + 1 and 2i + 2
Comparing
The new item and its parent
Console0 lines
Nothing has run yet. The heap is an ordinary array; the tree exists only in the index arithmetic.
Popping the minimum is the mirror image. Move the last item to index 0, then swap it with its smaller child until both children are larger.
Popping the minimum is the mirror image. Move the last item to index 0, then swap it with its smaller child until both children are larger.
Try it yourself
Change the code, predict the order, then run it for real in your browser.
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.
Pop: sift down
Removing the minimum takes the item at index 0, moves the last leaf into its place and pushes it down, swapping with the smaller of its two children until neither child is smaller. Again one path, so O(log n):
Press Run to see what your code prints, in order.
Runs in this browser, in an isolated frame with no access to this page. console.log, info, warn and error are shown; code runs as a classic script, so use an async function for await.
Popping everything returns the items in sorted order. That is heapsort: O(n log n), in place, but not stable, and it jumps around memory, so in practice it is mostly used as a safety net inside other sorts.
Where heaps show up
- Schedulers and timers: the next job or timeout to fire is the minimum by time. Many event loops keep their timers in a heap.
- Dijkstra's algorithm and A*: the next node to explore is the one with the smallest known distance.
- Merging k sorted lists: keep the head of each list in a heap and repeatedly take the smallest (
heapq.mergein Python). - Top-k: a min-heap of size k over a stream, as above, uses O(k) memory however long the stream is.
Building a heap from n items you already have can be done in O(n), not O(n log n), by sifting down from the middle of the array to the front (heapq.heapify). Python's heapq works on plain lists as a min-heap; Java has PriorityQueue; JavaScript has no built-in heap, so you write one like the above or use a library. A heap can't find or remove an arbitrary item quickly, so to change a priority you usually push a new entry and skip stale ones when they come out.