Understanding Stack and Queues in JavaScript
Tags: javascript, datastructures, webdev
Published: 2023-11-21 08:56:46

Stacks and Queues are commonly used data structures for extensive computer science and software development which depict a clear horizon for efficient data management, algorithm design, and task scheduling.

In this article, we will learn more about the principles and use cases used in the stack and queues.

**What is Stack?**

A stack is a data structure where the most recently added element can be accessed and removed. Think of stacks of nested coffee cups. You'll notice to access or remove the last coffee cup, you need to remove others from the top. This is where the principle of LIFO( Last In, First out) comes in. The LIFO principle dictates that the last element added to a stack would be the first to be removed when accessing the stacks. Its time complexity is denoted by a constant O(1). This illustration depicts a stack of cups.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0tt72eawdvru63w59zq.png)

**Use Cases**

Stacks are extensively used in memory management. For instance, in the local storage of application data, stacks efficiently store and manage data. Additionally, it is also used for undo features in software application, the undo features of an application often relies on stacks to track and update user actions.

**Methods**

Below are the methods that occur in the operations in stacks.

Push:

The push operation adds an element to the top of the stack.

Pop:

The pop operation removes and returns the element from the top of the stack.

Peek (or Top):

The peek operation returns the element at the top of the stack without removing or modifying it.

isEmpty:

The isEmpty operation checks whether the stack is empty. It returns true if the stack is empty and false otherwise.

**Concept**

Here, we'll build a shelve that contains different types of coffee cups.

Function

Let's define a function of Stack and also initialize `this.stack = []` as an empty array.

```
function Stack() {
    this.stack = [];
  }
```

Push

Define a `this.push` function to initialize and push items into the stack.

   

```
 // Function to push a value onto the stack
    this.push = function(coffeeCup) {
      this.stack.push(coffeeCup);
    };
```

Pop

Define a `this.pop` function to initialize and push items into the stack.

```
 // Function to pop a value onto the stack
    this.pop = function() {
      this.stack.push();
    };
```

Peek

Define a `this.peek` function to retrieve the top item without removing it.


 

```
      this.peek = function() {
      return this.stack[this.stack.length - 1];
    };
```

IsEmpty

Define a `this.isEmpty` function to check if the stack is empty.

```
this.isEmpty = function() {
      return this.stack.length === 0;
    };
```

Place all the code together

Put all the code we defined together to see what the whole flow looks like.

```
function CoffeeStack() {
    this.stack = [];

    // Function to push a value onto the stack
    this.push = function(coffeeCup) {
      this.stack.push(coffeeCup);
    };

 // Function to pop a value onto the stack
    this.pop = function() {
      this.stack.push();
    };

 // Function to pop a value onto the stack
       this.peek = function() {
      return this.stack[this.stack.length - 1];
    };

// Function to check if a stack is empty
this.isEmpty = function() {
      return this.stack.length === 0;
    };

  }
```
Let's test the Stack function.

Copy this code and place it outside the CoffeStack function.

```
let coffeCups = new CoffeeStack()
 // Pushing coffee cups onto the stack
  coffeeCups.push("Standard mug	");
  coffeeCups.push("Flat white cup");
  coffeeCups.push("Cappuccino Cup");
  
  // Peeking at the top coffee cup
  console.log("Top Coffee Cup:", coffeeCups.peek()); // Output: Top Coffee Cup: Cappuccino Cup
  
  // Popping a coffee cup from the stack
  let removedCup = coffeeCups.pop();
  console.log("Removed Coffee Cup:", removedCup); // Output: Removed Coffee Cup: Cappuccino Cup
  
  // Checking if the stack is empty
  console.log("Is the stack empty?", coffeeCups.isEmpty()); // Output: Is the stack empty? false
```


**Queues**

Queues are data structures that allow the First In, First Out (FIFO) principle. The FIFO principle dictates that the element that is added first is the one to be removed first. Queues share similar methods with Stack but the main distinction lies in the order or pattern of removal. Stack uses the Last In, First Out (LIFO) principle while queues make use of the First In, First Out (FIFO) principle to manage elements in a specific data structure.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zapahfp42tgxa2ajdam2.png)

**Use Cases**

Queues are generally used in shared printers. For instance, multiple users may send print jobs to a shared printer and during the whole process, the printer prints orderly as every user sends theirs.

**Methods**

Below are the queue methods used in everyday scenarios.

enqueue:

Adding or inserting elements to the top of the queue.

dequeue:

Removing elements from the top of the queue.

Peek (or Top):

The peek operation returns the element at the top of the queue.

isEmpty:

The isEmpty operation checks whether the queue is empty. It returns true if the queue is empty and false otherwise.

**Concept**

In the queue, we'll build a VehicleQueue that ordinates the FIFO principle.

Function

Let's define a function of VehicleQueue and also initialize `queue = []` as an empty array.

```
function VehicleQueue() {
    const queue = [];

  }
```

Enqueue

Define an enqueue function to add elements using the `queue.unshift(element)` unshift method which adds at the top of the queue.

 

```
   // Function to push a value onto the stack
   function enqueue(element) {
      queue.unshift(element);
    }
```

Dequeue

Define a dequeue() function to remove elements using the `queue.pop()` pop method which removes elements at the top queue.

```
    // Function to push a value onto the stack
     function dequeue() {
      queue.pop();
    }
```

Peek

Define a peek function to retrieve elements from the front of the queue without removing the element.

  

```
  // Function to peek a value into the queue
    function peek() {
      return queue[queue.length - 1];
    }
```

IsEmpty

Define a isEmpty() that checks if the queue is empty.


```
   function isEmpty() {
      return queue.length === 0;
    }
```

Place all the code together

```
function VehicleQueue() {
  const queue = [];

  function enqueue(element) {
    queue.unshift(element);
  }

  function dequeue() {
    queue.pop();
  }

  function peek() {
    return queue[queue.length - 1];
  }

  function isEmpty() {
    return queue.length === 0;
  }

  return { enqueue, dequeue, peek, isEmpty };
}


```
Let's test the Queue function.

Copy this code and place it outside the Queue function.

```
const myQueue = VehicleQueue();
myQueue.enqueue("volvo");
myQueue.enqueue("volvo");

console.log("Peek:", myQueue.peek()); // Output: car1
myQueue.dequeue();
console.log("Peek:", myQueue.peek()); // Output: car2
console.log("Is Empty:", myQueue.isEmpty()); // Output: false
```

**Conclusion**

In the context of using stacks and queues in our article, I hope it helps you understand the use cases and principle underlying the breakdown of some certain processes. Moreover, how can you approach explaining stacks and queues, and are there any other use cases you would consider? Let us know in the comment section.