STL: Stack, Queue and Priority Queue · Lesson 24 of 33
Priority Queue (Heap) in C++ STL
A priority queue always gives you the most important element first – the largest number, the earliest deadline, the shortest distance. std::priority_queue is implemented as a binary heap: inserting and removing take O(log n), and reading the top is O(1). It powers Dijkstra's algorithm, schedulers and every "top K" interview question.
In this lesson
- Max heap by default
- Min heaps with
std::greater - Pairs and custom comparators
- Top K, merge K sorted lists and running median
Max heap: the default
#include <iostream>
#include <queue>
int main() {
std::priority_queue<int> pq;
for (int x : {30, 10, 50, 20, 40}) pq.push(x); // O(log n) each
std::cout << "top " << pq.top() << ", size " << pq.size() << '\n';
while (!pq.empty()) {
std::cout << pq.top() << ' '; // largest first
pq.pop();
}
std::cout << '\n';
return 0;
}
top 50, size 5 50 40 30 20 10
The heap after pushing 30, 10, 50, 20, 40 – every parent ≥ its children (stored as the array 50 40 30 10 20)
50
- 40children 10 and 20
- 30a leaf
The heap only guarantees the top is the largest; the rest isn't sorted. Push adds at the end and "sifts up"; pop moves the last element to the top and "sifts down" – both O(log n).
Min heap
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
int main() {
std::priority_queue<int, std::vector<int>, std::greater<int>> minq; // smallest first
for (int x : {30, 10, 50, 20, 40}) minq.push(x);
while (!minq.empty()) { std::cout << minq.top() << ' '; minq.pop(); }
std::cout << '\n';
std::priority_queue<int> trick; // contest trick: push negatives
for (int x : {30, 10, 50}) trick.push(-x);
std::cout << "smallest via negation: " << -trick.top() << '\n';
return 0;
}
10 20 30 40 50 smallest via negation: 10
Pairs and custom comparators
#include <functional>
#include <iostream>
#include <queue>
#include <string>
#include <utility>
#include <vector>
struct Task {
std::string name;
int priority; // higher = more urgent
int order; // arrival order, for ties
};
struct LessUrgent { // returns true if a should come AFTER b
bool operator()(const Task& a, const Task& b) const {
if (a.priority != b.priority) return a.priority < b.priority;
return a.order > b.order; // earlier arrival first on ties
}
};
int main() {
using Item = std::pair<int, std::string>; // (distance, city)
std::priority_queue<Item, std::vector<Item>, std::greater<Item>> nearest;
nearest.push({12, "Pune"});
nearest.push({5, "Lonavala"});
nearest.push({30, "Nashik"});
std::cout << "nearest: " << nearest.top().second << " (" << nearest.top().first << " km)\n";
std::priority_queue<Task, std::vector<Task>, LessUrgent> tasks;
tasks.push({"reply email", 1, 0});
tasks.push({"fix outage", 5, 1});
tasks.push({"review PR", 3, 2});
tasks.push({"deploy", 5, 3});
while (!tasks.empty()) { std::cout << tasks.top().name << " | "; tasks.pop(); }
std::cout << '\n';
return 0;
}
nearest: Lonavala (5 km) fix outage | deploy | review PR | reply email |
The comparator is "backwards"
A priority_queue puts on top the element that is not less than the others according to its comparator. With the default std::less the largest is on top; to put the smallest on top you pass std::greater. Think of the comparator as "a has lower priority than b".
Top K elements
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
std::vector<int> top_k(const std::vector<int>& nums, int k) {
std::priority_queue<int, std::vector<int>, std::greater<int>> heap; // min heap of size k
for (int x : nums) {
heap.push(x);
if (static_cast<int>(heap.size()) > k) heap.pop(); // drop the smallest
}
std::vector<int> result;
while (!heap.empty()) { result.push_back(heap.top()); heap.pop(); }
return result; // ascending order
}
int main() {
std::vector<int> scores{45, 92, 13, 78, 88, 61, 99, 70};
for (int s : top_k(scores, 3)) std::cout << s << ' ';
std::cout << '\n';
return 0;
}
88 92 99
Keeping a min heap of size k gives O(n log k) – much better than sorting everything (O(n log n)) when k is small, and it works on streams too.
Running median with two heaps
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
int main() {
std::priority_queue<int> low; // max heap: smaller half
std::priority_queue<int, std::vector<int>, std::greater<int>> high; // min heap: larger half
for (int x : {5, 15, 1, 3, 8, 7}) {
if (low.empty() || x <= low.top()) low.push(x); else high.push(x);
if (low.size() > high.size() + 1) { high.push(low.top()); low.pop(); } // rebalance
else if (high.size() > low.size()) { low.push(high.top()); high.pop(); }
double median = low.size() > high.size() ? low.top() : (low.top() + high.top()) / 2.0;
std::cout << "after " << x << ": median " << median << '\n';
}
return 0;
}
after 5: median 5 after 15: median 10 after 1: median 5 after 3: median 4 after 8: median 5 after 7: median 6
Practice
Try it yourself
Connect ropes of lengths {4, 3, 2, 6} with minimum total cost, where joining two ropes costs their total length (always join the two shortest).
Show solution
#include <functional> #include <iostream> #include <queue> #include <vector> int main() { std::priority_queue<long long, std::vector<long long>, std::greater<long long>> ropes; for (int r : {4, 3, 2, 6}) ropes.push(r); long long cost = 0; while (ropes.size() > 1) { long long a = ropes.top(); ropes.pop(); long long b = ropes.top(); ropes.pop(); cost += a + b; ropes.push(a + b); } std::cout << "minimum cost " << cost << '\n'; return 0; }minimum cost 29
Quick check
Is std::priority_queue a max heap or a min heap by default?
A max heap.
How do you make a min heap?
std::priority_queue<T, std::vector<T>, std::greater<T>> (or push negatives).
What is the cost of push and pop?
O(log n); top() is O(1).
Summary
- priority_queue is a binary heap: O(log n) push/pop, O(1) top; max heap by default.
- Use std::greater (or negation) for a min heap; custom comparators mean "a has lower priority".
- Heaps solve top K, merging, scheduling, running median and Dijkstra.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.