Skip to content
DSA heaps 8 min read

Priority Queues: The Built-in Heap in Each Language

A priority queue is an abstract data type where you always remove the highest-priority element next, rather than the oldest (a queue) or newest (a stack). It is almost always implemented with a binary heap, so the operations cost O(log n) to push and pop and O(1) to peek. Three of our four languages ship one in the standard library; JavaScript does not, so you implement a small heap yourself.

The one thing that trips everyone up: the default direction

Each language’s default is different. Get this wrong and your “min” queue silently returns maxes.

LanguageBuilt-inDefault orderTop =
C++std::priority_queuemax-heaplargest
JavaPriorityQueuemin-heapsmallest
Pythonheapq (functions on a list)min-heapsmallest
JavaScriptnone — write your ownup to youup to you

For beginners: “Priority” just means which one comes out first. A max-priority-queue serves the biggest value first; a min-priority-queue serves the smallest. Always confirm the default before trusting it.

Push, peek, pop in each language

Here we push a few numbers and pop them in priority order. To make the behaviour identical across languages, each snippet builds a min-priority-queue (smallest comes out first), overriding the C++ default.

#include <queue>
#include <vector>
// Min-heap: greater<int> flips the default max-heap.
std::priority_queue<int, std::vector<int>, std::greater<int>> pq;
pq.push(5); pq.push(1); pq.push(3);
int top = pq.top();   // 1  (peek, O(1))
pq.pop();             // removes 1, O(log n)
// remaining tops would be 3, then 5

Note for JavaScript: there is no PriorityQueue in the language or standard runtime. The MinHeap class above is the documented, idiomatic approach — the same sift-up/sift-down logic from heap operations. For a max-heap, flip the two comparisons (>= to <=, and < to >).

Making a max-priority-queue

Each language has a clean idiom for the other direction:

#include <queue>
// Default IS a max-heap — largest on top.
std::priority_queue<int> maxpq;
maxpq.push(5); maxpq.push(1); maxpq.push(3);
int top = maxpq.top(); // 5

Storing more than numbers: keyed priorities

Real priority queues order objects by a key. Use a comparator (C++/Java/JS) or a (priority, item) tuple (Python):

#include <queue>
#include <string>
#include <vector>
struct Task { int priority; std::string name; };
struct ByPriority {
    bool operator()(const Task& a, const Task& b) const {
        return a.priority > b.priority; // min by priority
    }
};
std::priority_queue<Task, std::vector<Task>, ByPriority> pq;
pq.push({2, "email"});
pq.push({1, "alarm"});
std::string next = pq.top().name; // "alarm"

Going deeper: Standard-library priority queues do not support efficient “decrease-key” (changing an element’s priority in place). The common workaround — used in Dijkstra’s algorithm — is lazy deletion: push the updated entry and skip stale ones when popped.

Next, see the O(n) build and heap sort, or practice on the heap exercises.

Last updated June 25, 2026
Was this helpful?