Priority Queue Data Structure and Heaps Implemented in JavaScript _ Adrian Mejia Blog
Priority Queue Data Structure and Heaps Implemented in JavaScript _ Adrian Mejia Blog
A priority queue is a versatile data structure that is good to have under your
algorithmic toolbelt. In this post, we discuss, what it is, real-world applications, and we
explore two different implementations, the latter one being more robust.
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 1/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
The priority queue adds a priority to each element’s value. If we go back to the
example of a line of people in a supermarket. You can add preferred lanes, for
example, Seniors (65+ years old) and pregnant women. If you have Seniors in the
line, you will take them first, even if other people arrived before them. That’s what a
priority queue (PQ) does. If all elements in a PQ have the same priority, then it will
behave like a regular queue.
Why a priority queue? Can’t we just have different queues for each priority? That only
works if you have a few priorities, but sometimes you have infinite possibilities (e.g.,
the distance between two points, ETA, etc.). Later in this post, we will explore how we
can implement an efficient solution for these cases.
System to triage hospital patients and attend them by their severity order.
Forward network packages in order of urgency (e.g., “real-time video call” should
go before “time sync checks,” so to speak)
Scheduling tasks in a system: “critical” goes before “shadow drawing” for
instance.
Asynchronous control flows like firing events (or notifying observers) in a certain
order.
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 2/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
This tutorial will start with a simple implementation and then build it to a robust
implementation while making it easy to follow.
Priority queue usually has a comparison function. Since our data could be simple (just
an array of numbers where the value and priority are the same) or compound, where
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 3/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
we have multiple fields (e.g. the priority could be the age of a student object). The
comparator function tells our PQ what we can use as a priority. Here’s an example:
As you can see, the comparator function dequeue elements with the highest age first.
This is called a Max-PQ. We can invert the minuend and subtrahend to get a Min-PQ.
Another possibility to use the name as a priority.
Now that we have a general idea of how a PQ API works let’s explore how we can
implement it.
You can implement a regular queue using an array or linked list. However, priority
queues have a new dimension: It needs to sort elements by priority. So, can we just
sort a regular array queue every time we insert a new element? Yes, we can! But let’s
see how it will perform.
Enqueue
Every time we insert a new element, we need to sort the elements. That’s O(n log
n).
Complexity
Time: O(n log n), insertion into an array is constant but sorting takes n log n.
Space: O(n), the space used in memory will grow proportionally to the number of
elements in the queue.
1 class NaivePQ {
2 constructor(comparator = (a, b) => a - b) {
3 this.array = [];
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 4/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
4 this.comparator = comparator;
5 }
6
7 /**
8 * Insert element
9 * @runtime O(n log n)
10 * @param {any} value
11 */
12 add(value) {
13 this.array.push(value);
14 this.array.sort(this.comparator);
15 }
16
17 //...
18 }
Dequeue
Dequeue removes elements from the PQ. We need to find the element with the
highest priority and then return that. The highest number will be first element, so
that’s O(1) operation. However, we need to move the rest of the elements to fill the
gap. That’s O(n).
Complexity
1 /**
2 * Retrieves and removes the head or returns null if this Heap is empty
3 * @runtime O(n)
4 */
5 remove() {
6 if (!this.size) return null;
7 const value = this.array.shift(); // remove element
8 return value;
9 }
Improving PQ implementation
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 5/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
Can we do better? We could do nothing after insertion O(1) and then delegate the
finding of the element with the highest priority to dequeue (if max-heap). That would
be O(n).
O(n) as time complexity is not bad. It’s better than sorting all elements on every
insertion O(n log n). Still, how can we improve this? If we use a data structure that
keeps the max element at the top in less than O(n), that would be great! Good news,
that’s what a heap is for!
A heap is a tree data structure that keeps to max or min element at the root. So you
can have a max-heap or min-heap. Regardless, they have two basic operations:
insert and remove.
Conceptually the heaps can be represented as a complete binary tree. With the
following rules or invariants:
1. The parent node should be smaller (or equal) than the two children for a Min-
Heap. For a max-heap is the opposite, the parent node should be bigger (or
equal) than the two children.
2. The binary tree should be complete (all levels are completely filled. The only
exception is the last level which might not be full, but the ones filled comes from
left to right without gaps)
parent(i) = Math.ceil(i / 2 - 1)
leftChild(i) = 2 * i + 1
rightChild2(i) = 2 * i + 2
Again the PQ has two primary operations: enqueue and dequeue. So, let’s see how
we can do this with a heap.
Enqueue
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 7/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
invariant is broken, fix it by swapping the node with its parent and repeat the
process all the way to the root node if necessary.
1 class Heap {
2 constructor(comparator = (a, b) => a - b) {
3 this.array = [];
4 this.comparator = (i1, i2) => comparator(this.array[i1], this.arra
5 }
6
7 /**
8 * Insert element
9 * @runtime O(log n)
10 * @param {any} value
11 */
12 add(value) {
13 this.array.push(value);
14 this.bubbleUp();
15 }
16
17 /**
18 * Move new element upwards on the Heap, if it's out of order
19 * @runtime O(log n)
20 */
21 bubbleUp() {
22 let index = this.size - 1;
23 const parent = (i) => Math.ceil(i / 2 - 1);
24 while (parent(index) >= 0 && this.comparator(parent(index), index)
25 this.swap(parent(index), index);
26 index = parent(index);
27 }
28 }
29 }
This algorithm can keep a heap sorted in O(log n) because it only visits half of the
tree at most.
Because that’s the maximum number of swaps that you would have to bubble up the
newly inserted element.
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 8/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
Complexity:
Time: O(log n), in the worst case, you will have to bubble up the inserted
element up to the root of the tree. These will involve log n swaps, where n is the
total number of nodes.
Space: O(n)
Dequeue
Complexity:
Time: O(log n), The maximum number of swaps is given by the tree’s height,
which is log n.
Space: O(n).
1 /**
2 * Retrieves and removes the head of this Heap or returns null if this
3 * @runtime O(log n)
4 */
5 remove(index = 0) {
6 if (!this.size) return null;
7 this.swap(index, this.size - 1); // swap with last
8 const value = this.array.pop(); // remove element
9 this.bubbleDown(index);
10 return value;
11 }
12
13 /**
14 * After removal, moves element downwards on the Heap, if it's out of
15 * @runtime O(log n)
16 */
17 bubbleDown(index = 0) {
18 let curr = index;
19 const left = (i) => 2 * i + 1;
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 9/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
Summary
In these post we learned about the usages of a priority queue and how to implement
it with an array+sorting and using array-based heap. We also explored it’s time
complexity for each implementation so we can verify that the heap implementation is
more efficient.
OLDER
2020 recap and how I got my dream job
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 10/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
email address
Subscribe
Follow @iAmAdrianMejia
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 11/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 12/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
8 time complexities
that every programmer
should know
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 13/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
Data Structures in
JavaScript: Arrays,
HashMaps, and Lists
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 14/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
Self-balanced Binary
Search Trees with AVL
in JavaScript
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 15/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
Analysis of Recursive
Algorithms
Contents
1. What’s a Priority Queue (PQ)?
2. What is a priority queue good for? / Applications
3. Summary
6 years ago • 1 comment 6 years ago • 5 comments 6 years ago • 11 comments 6 years ago
JavaScript tutorials and web JavaScript tutorials and web JavaScript tutorials and web JavaScript
development articles development articles development articles developme
including topics like … including topics like … including topics like … including to
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 16/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog
1 Comment
1 Login
Name
Javohir − ⚑
J 3 years ago
parent(i) = Math.ceil(i / 2 - 1)
leftChild(i) = 2 * i + 1
rightChild(i) = 2 * i + 2
0 0 Reply ⥅
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 17/17