A complete binary tree stored in an array, satisfying the heap property: every node is (min-heap) or (max-heap) its children.

Array layout

For a 0-indexed array: node has children and , and parent . No pointers, perfect cache locality.

OperationCost
top
push — append, then sift up
pop — move the last element to the root, sift down
build from an array — sift down from the last internal node backwards
decrease-key, but needs an index map
merge two heaps — binary heaps do not merge cheaply

Build is , not : most nodes are near the leaves and sift down only a little. The sum converges to .

In C++

priority_queue<int> maxHeap;                                        // max by default
priority_queue<int, vector<int>, greater<int>> minHeap;             // min
priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;  // Dijkstra
 
// custom comparator
auto cmp = [](const Item& a, const Item& b) { return a.cost > b.cost; };  // min-heap
priority_queue<Item, vector<Item>, decltype(cmp)> q(cmp);
 
// build in O(n)
priority_queue<int> h(a.begin(), a.end());

The comparator is inverted

priority_queue puts the element the comparator considers largest on top. So greater<> yields a min-heap, and a custom cmp returning a > b also yields a min-heap. This trips up nearly everyone at least once.

No decrease-key — use lazy deletion instead

std::priority_queue cannot update an element. The standard workaround, and the one used in every Dijkstra implementation:

pq.push({newDist, v});                      // push a new entry, leave the stale one
...
auto [d, u] = pq.top(); pq.pop();
if (d > dist[u]) continue;                  // skip stale entries

The queue grows to instead of , but the complexity is unchanged and the code is much simpler than an indexed heap.

When you genuinely need decrease-key (or erase), use std::set as a heap — for everything including deletion, at the cost of a worse constant.

The heap family

Heappushpopdecrease-keymerge
Binary
Binomial
Fibonacci am. am. am.
Pairing am. am.
Leftist / skew

Binary heaps win in practice on constant factor; the others exist for their merge or decrease-key. See Advanced Heaps.

Uses

  • Dijkstra, Prim, A*
  • Huffman coding — repeatedly merge the two smallest
  • Heap sort, in place, not stable
  • -th largest, top — keep a size- min-heap
  • Merging sorted lists — heap of list heads,
  • Median of a stream — two heaps, a max-heap for the lower half and a min-heap for the upper
  • Event simulation / sweep lines — process events in time order
  • Slope trick — the entire technique is two heaps

The two-heap median trick

Maintain lo (max-heap, smaller half) and hi (min-heap, larger half), rebalancing so their sizes differ by at most 1. The median is lo.top() (odd count) or the average of both tops (even). per insertion — a fifteen-line answer to “running median”, which is otherwise awkward.

See also: Advanced Heaps · Sorting · Dijkstra