0% found this document useful (0 votes)
10 views

Priority Queue Data Structure and Heaps Implemented in JavaScript _ Adrian Mejia Blog

Uploaded by

lonesome.rar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Priority Queue Data Structure and Heaps Implemented in JavaScript _ Adrian Mejia Blog

Uploaded by

lonesome.rar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog

 

Home Trending Popular About Blog

Programming > Data Structures and Algorithms (DSA)

Priority Queue Data Structure and


Heaps Implemented in JavaScript
 Last updated July 5th 2021  6.8k 0 Comments  algorithms big-o
notation tutorial_algorithms

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.

What’s a Priority Queue (PQ)?


A priority queue is a data structure that extends the queue by a priority dimension.
Let’s expand both terms. The queue is a list of elements taken in the same order as
they arrived. For instance, a line of people waiting to pay at the Supermarket behaves
like a queue: first-in, first-served, or FIFO (first in, first out).

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.

What is a priority queue good for? /


Applications
There are many real-world applications for priority queues, such as:

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

Keeping track of top k elements efficiently


Keeping track of median numbers in constant time
Used in some graph algorithms like Dijkstra for finding the shortest path between
two points. The distance among points is used as a priority.

Some priority queue JavaScript implementations on the wild:

closure-library: heap.js, priorityqueue.js


dsa.js: heap.js, priority-queue.js, min-heap.js, max-heap.js
async : priorityQueue.js, Heap.js.
datastructures-js: heap.js, priorityQueue.js

This tutorial will start with a simple implementation and then build it to a robust
implementation while making it easy to follow.

Implementing a Priority Queue (PQ) in JavaScript


JavaScript standard doesn’t provide a default implementation that we can use. So,
we are going to define our own. But, even if you use another language that has it in
their standard API, it’s still good to know how it works so you can reason about the
time complexity of their operations.

Without any further ado, let’s get to it!

Priority Queue operations


As always, there are many ways to solve the same problem. We are going to
brainstorm some approaches along with their pros and cons. Yes, there’s never a
perfect approach. However, we can learn to analyze the trade-offs and how we can
improve our algorithms better.

The essential operations of the priority queue are:

enqueue: insert elements on the queue


dequeue: remove elements from the queue in the same order they were
inserted.

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:

1 const pq= new PriorityQueue((x, y) => y.age - x.age);


2 pq.enqueue({ name: 'Maria', age: 23 });
3 pq.enqueue({ name: 'Nushi', age: 42 });
4 pq.enqueue({ name: 'Jose', age: 32 });
5
6 pq.dequeue(); // { name: 'Nushi', age: 42 }
7 pq.dequeue(); // { name: 'Jose', age: 32 }
8 pq.dequeue(); // { name: 'Maria', age: 23 }

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.

Naive: Priority Queue implemented using Array + Sorting

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.

Here’s the implementation of the Enqueue method:

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

Time: O(n), finding the top element.


Space: O(n), space is technically O(n-1). However, we just care about the
“higher order” term, so O(n).

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!

Priority Queue implemented using a Heap

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)

Even though a heap is conceptually a binary tree, it can be implemented using an


array since it’s a complete tree. The first element on the array is the root. The
following two elements are the root’s children, the 4th and 5th elements are the 2nd
element’s children, and so on.
https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 6/17
1/10/25, 9:47 AM Priority Queue Data Structure and Heaps Implemented in JavaScript | Adrian Mejia Blog

You can calculate the following formula to translate tree to array:

parent(i) = Math.ceil(i / 2 - 1)
leftChild(i) = 2 * i + 1
rightChild2(i) = 2 * i + 2

What’s the time complexity of heaps and Priority Queue?

Again the PQ has two primary operations: enqueue and dequeue. So, let’s see how
we can do this with a heap.

Enqueue

The algorithm to insert an element in a heap is as follows:

1. Insert the element into the next empty position (tail).


2. From that position, “bubble up” the element to keep the min-heap invariant
“parent should be smaller than any children” (the opposite if max-heap). If the

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.

Here’s an implementation of the Heap. Also we are using a comparator function so


we can define the priority.

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.

“Why log n?“**,** you asked.

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

I see, but where did you get that log n from?

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

The algorithms for dequeuing an element from a PQ is the following:

1. Remove the root element


2. Since the root element is gone, you need to fill the hole by promoting a child to
take its place. This process is called “heapify” or bubbleDown . You choose the
child that has the min value for min-heap (or max value for max-heap). You do
this recursively until you found a leaf (node without children).

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

20 const right = (i) => 2 * i + 2;


21 const getTopChild = (i) => (right(i) < this.size
22 && this.comparator(left(i), right(i)) > 0 ? right(i) : left(i));
23
24 while (left(curr) < this.size && this.comparator(curr, getTopChild(c
25 const next = getTopChild(curr);
26 this.swap(curr, next);
27 curr = next;
28 }
29 }

You can find the full implementation at: https://github.com/amejiarosario/dsa.js-data-


structures-algorithms-javascript/blob/master/src/data-structures/heaps/heap.js

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

Subscribe & stay up to date!

email address

Subscribe

About the author

Adrian Mejia is a Software Engineer located in Boston, MA.


Currently working at Google. Adrian enjoys writing posts about
Algorithms, programming, JavaScript, and Web Dev. Also, he likes
to travel ✈️ and biking 🚴‍.

Follow @iAmAdrianMejia

Tutorial Algorithms Series

How to find time


complexity of an
algorithm?

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

How to solve any


graph/Maze interview
questions in
JavaScript? DFS vs.
BFS

Priority Queue Data


Structure and Heaps
Implemented in
JavaScript

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

How you can change


the world by learning
Data Structures and
Algorithms

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

Graph Data Structures


in JavaScript for
Beginners

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

Tree Data Structures in


JavaScript for
Beginners

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

 Top  Edit this post

Contents
1. What’s a Priority Queue (PQ)?
2. What is a priority queue good for? / Applications
3. Summary

ALSO ON ADRIAN MEJIA'S BLOG

Overview of JavaScript Building a Node.js static How to build a Node.js Overview


ES6 features (a.k.a … file server (files over … eCommerce website … ES6 featu

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

G Join the discussion…

LOG IN WITH OR SIGN UP WITH DISQUS ?

Name

 Share Best Newest Oldest

Javohir − ⚑
J 3 years ago

There is typo in array -> binary tree calculation. Should be:

parent(i) = Math.ceil(i / 2 - 1)
leftChild(i) = 2 * i + 1
rightChild(i) = 2 * i + 2

0 0 Reply ⥅

Subscribe Privacy Do Not Sell My Data

© 2022 Adrian Mejia v.rk61qc

https://adrianmejia.com/priority-queue-data-structure-and-heaps-time-complexity-javascript-implementation/ 17/17

You might also like