JavaScript queue data structure implementation tutorial

The Queue data structure is a linear data structure that allows you to store a collection of data inside it in a similar fashion to a real-world queue.

Whenever you’re going to a bank or buying a Starbucks coffee, you’re most likely going to form a line with other people and wait until it’s your turn to be served. A queue always implements the FIFO (First-In-First-Out) system. Those who came in earliest will be served first.

The process of adding a new customer to the line is called enqueue, while a customer that has been served by the store and removed from the line is called the dequeue process.

The Queue data structure mimics this real-world practice of waiting in line and serving the earliest customer first by creating an abstract rule that you need to implement to the data structure. The rules are as follows:

  • The data structure has 2 pointers: the head and the tail
  • The earliest element will be located on the head
  • The latest element will be located on the tail
  • A new element can be inserted into the structure using enqueue() method
  • The dequeue() method will remove the element on the head, moving the head to the next element in line

In addition, you may also count the length of the queue and peek to see the next element located in the head pointer to help with data manipulation. I will show you how to implement both additions later.

Here’s an illustration explaining how Queue data structure works:

The Queue data structure is commonly used because its fast insertion and deletion. The following table describes Queue data structure time complexity in Big O Notation (from Wikipedia):

AlgorithmAverageWorst case
SpaceO(n)O(n)
SearchO(n)O(n)
InsertO(1)O(1)
DeleteO(1)O(1)

Now that you understand what the queue data structure looks like, let’s learn how to implement one using JavaScript.

JavaScript Queue implementation

You can implement a Queue data structure using JavaScript in three steps:

  • Create a class named Queue with three properties: elements, head, and tail
  • Write the length function and bind it as a property using get syntax
  • Write the enqueue(), dequeue(), and peek() method code

You will use the class as a blueprint to create a new object instance of Queue. Alright, let’s start with creating a Queue class that has the required properties:

class Queue {
  constructor() {
    this.elements = {};
    this.head = 0;
    this.tail = 0;
  }
}

Any element enqueued to the object instance will be stored in elements property. The head and tail properties will be the pointer, indicating the first and last element index inside the structure.

Next, write the length() method code as follows:

get length() {
  return this.tail - this.head;
}

The get syntax before the length() method declaration will bind the method as a property, so when you create a new instance later, you can call the method like a property:

const q = new Queue();
q.length; // calls the length() method

Finally, you need to write the three methods for enqueue(), dequeue(), and peek() process.

The enqueue() method takes an element as its parameter and puts it in the tail index. Once the new element is stored, you need to increment the tail pointer by one:

enqueue(element) {
  this.elements[this.tail] = element;
  this.tail++;
}

The dequeue() method first check if the length property of the instance is larger than zero. When there’s no element, the method simply returns undefined. When there is one or more element in the instance, the method will grab the element at head index and delete it from the storage (elements property in this case)

Then, the head pointer will be incremented by one and the deleted element is returned to the caller.

Here’s the code for dequeue() method:

dequeue() {
  if (this.length) {
    const element = this.elements[this.head];
    delete this.elements[this.head];
    this.head++;
    return element;
  }
  return undefined;
}

Finally, the peek() method will return the next element waiting in line. This will be the same element returned by dequeue() method, but the difference is this element won’t be removed from the queue.

Here’s the code for the peek() method:

peek() {
  if (this.length) {
    return this.elements[this.head];
  }
  return undefined;
}

And with that, your Queue class is finished. Here’s the full code for your reference:

class Queue {
  constructor() {
    this.elements = {};
    this.head = 0;
    this.tail = 0;
  }

  get length() {
    return this.tail - this.head;
  }

  enqueue(element) {
    this.elements[this.tail] = element;
    this.tail++;
  }

  dequeue() {
    if (this.length) {
      const element = this.elements[this.head];
      delete this.elements[this.head];
      this.head++;
      return element;
    }
    return undefined;
  }

  peek() {
    if (this.length) {
      return this.elements[this.head];
    }
    return undefined;
  }
}

You can test the code by creating a new object of Queue class instance and call the methods from it:

const q = new Queue();
q.enqueue("James");
q.enqueue("Dean");
q.enqueue("Ben");
console.log(q.length); // 3
console.log(q.peek()); // "James"
console.log(q.dequeue()); // "James"
console.log(q.peek()); // "Dean"
console.log(q.length); // 2

Feel free to copy and use the code as you need 😉

Take your skills to the next level ⚡️

I'm sending out an occasional email with the latest tutorials on programming, web development, and statistics. Drop your email in the box below and I'll send new stuff straight into your inbox!

No spam. Unsubscribe anytime.