Deque data structure with doubly linked list

We will see what is deque data structure and how to implement deque with the doubly linked list in javascript.

Deque or Double-ended queue is a generalized version of queue in which data can be added or removed from both the ends.

Deque Data Structure

It works like both a stack and queue and can be used as any of them.

We have already implemented the Deque data structure with the circular array, but here we will see how can we implement deque with a doubly-linked list.

List of operations performed on Deque

  • insertFront(): Inserts an element at the front.
  • insertBack(): Inserts an element at the back.
  • removeFront(): Removes an element from the front.
  • removeBack(): Removes an element from the back.
  • getFront(): Returns the element at the front.
  • getBack(): Returns the element at the back.
  • isEmpty(): Checks if the deque is empty or not.
  • size(): Returns the size of the deque.
  • clear(): Clears the deque.
  • toString(): Returns all the elements concatenated as a string from front to back.

Implementing deque with doubly linked list

We will create a function and use the double linked list to create the Deque data structure.

function dequeWithDLL() {
  //create a doubly linked list object
  let dll = new doubleLinkedList();

  //other methods go here
}

Adding an item on the front

To add a new item on the front we just need to append the data in the list.

//Add an item on the front
  this.insertFront = (elm) => {
    dll.append(elm);
    return true;
  }

Adding an item on the back

To add a new item on the back we just need to insert the data after the last index.

//Add an item on the back
  this.insertBack = (elm) => {
    let length = dll.size();
    dll.insert(length, elm);
    return true;
  }

Remove an item from the front

To remove the item from front we just need to delete the head of the list.

//Remove item from the front
  this.removeFront = () => {
    return dll.deleteHead();
  }

Remove an item from the back

To remove the item from back we just need to delete the tail of the list.

//Remove item from the back
  this.removeBack = () => {
    return dll.deleteTail();
  }

Get the first element from the front

To peek the first element of the the front just get the head and return its element.

//Peek the front element
  this.getFront = () => {
    let head = dll.getHead();
    return head && head.element;
  }

Get the first element from the back

To peek the first element of the the back just get the tail and return its element.

//Peek the back element
  this.getBack = () => {
    let tail = dll.getTail();
    return tail && tail.element;
  }

Check if deque is empty

//Check if empty
  this.isEmpty = () => {
    return dll.isEmpty();
  }

Get the size of the deque

//Get the size
  this.size = () => {
    return dll.size();
  }

Clear the deque

//Clear the deque
  this.clear = () => {
    dll = new doubleLinkedList();
  }

Get the deque element as a string

//Convert to the string
  //From front to back
  this.toString = () => {
    if (this.isEmpty()) {
      return '';
    }
    
    let current = dll.getHead();
    let objString = '';
    while(current){
      objString = current.element + ' ' + objString;
      current = current.next;
    }
    
    return objString.trim();
  }

Complete code of deque with doubly linked list

function dequeWithDLL() {
  let dll = new doubleLinkedList();
  
  //Add an item on the front
  this.insertFront = (elm) => {
    dll.append(elm);
    return true;
  }
  
  //Add an item on the back
  this.insertBack = (elm) => {
    let length = dll.size();
    dll.insert(length, elm);
    return true;
  }
  
  //Remove item from the front
  this.removeFront = () => {
    return dll.deleteHead();
  }
  
  //Remove item from the back
  this.removeBack = () => {
    return dll.deleteTail();
  }
  
  //Peek the front element
  this.getFront = () => {
    let head = dll.getHead();
    return head && head.element;
  }
  
  //Peek the back element
  this.getBack = () => {
    let tail = dll.getTail();
    return tail && tail.element;
  }
  
  //Check if empty
  this.isEmpty = () => {
    return dll.isEmpty();
  }
  
  //Get the size
  this.size = () => {
    return dll.size();
  }
  
  //Clear the deque
  this.clear = () => {
    dll = new doubleLinkedList();
  }
  
  //Convert to the string
  //From front to back
  this.toString = () => {
    if (this.isEmpty()) {
      return '';
    }
    
    let current = dll.getHead();
    let objString = '';
    while(current){
      objString = current.element + ' ' + objString;
      current = current.next;
    }
    
    return objString.trim();
  }
}
Input:
let deque = new dequeWithDLL();
deque.insertBack(5);
deque.insertBack(10);
console.log(deque.getBack());
deque.removeBack();
console.log(deque.getBack());
deque.insertFront(15);
console.log(deque.getFront());
deque.removeFront(); 
console.log(deque.getFront());
console.log(deque.toString());

Output:
5
5
15
"15"

Making the properties and methods private with closure and IIFE (Immediately Invoked Function Expression).

let dequeWithDLL = (function(){
  return function DequeWithDLL() {
    let dll = new doubleLinkedList();

    //Add an item on the front
    this.insertFront = (elm) => {
      dll.append(elm);
      return true;
    }

    //Add an item on the back
    this.insertBack = (elm) => {
      let length = dll.size();
      dll.insert(length, elm);
      return true;
    }

    //Remove item from the front
    this.removeFront = () => {
      return dll.deleteHead();
    }

    //Remove item from the back
    this.removeBack = () => {
      return dll.deleteTail();
    }

    //Peek the front element
    this.getFront = () => {
      let head = dll.getHead();
      return head && head.element;
    }

    //Peek the back element
    this.getBack = () => {
      let tail = dll.getTail();
      return tail && tail.element;
    }

    //Check if empty
    this.isEmpty = () => {
      return dll.isEmpty();
    }

    //Get the size
    this.size = () => {
      return dll.size();
    }

    //Clear the deque
    this.clear = () => {
      dll = new doubleLinkedList();
    }

    //Convert to the string
    //From front to back
    this.toString = () => {
      if (this.isEmpty()) {
        return '';
      }

      let current = dll.getHead();
      let objString = '';
      while(current){
        objString = current.element + ' ' + objString;
        current = current.next;
      }

      return objString.trim();
    }
  }
}());
Input:
let deque = new dequeWithDLL();
deque.insertBack(5);
deque.insertBack(10);
console.log(deque.getBack());
deque.removeBack();
console.log(deque.getBack());
deque.insertFront(15);
console.log(deque.getFront());
deque.removeFront(); 
console.log(deque.getFront());
console.log(deque.toString());

Output:
5
5
15
"15"

Class based implementation of deque with doubly linked list

class dequeWithDLL {
  constructor(){
    this.dll = new doubleLinkedList();
  }
  
  //Add an item on the front
  insertFront = (elm) => {
    this.dll.append(elm);
    return true;
  }

  //Add an item on the back
  insertBack = (elm) => {
    let length = this.dll.size();
    this.dll.insert(length, elm);
    return true;
  }

  //Remove item from the front
  removeFront = () => {
    return this.dll.deleteHead();
  }

  //Remove item from the back
  removeBack = () => {
    return this.dll.deleteTail();
  }

  //Peek the front element
  getFront = () => {
    let head = this.dll.getHead();
    return head && head.element;
  }

  //Peek the back element
  getBack = () => {
    let tail = this.dll.getTail();
    return tail && tail.element;
  }

  //Check if empty
  isEmpty = () => {
    return this.dll.isEmpty();
  }

  //Get the size
  size = () => {
    return this.dll.size();
  }

  //Clear the deque
  clear = () => {
    this.dll = new doubleLinkedList();
  }

  //Convert to the string
  //From front to back
  toString = () => {
    if (this.isEmpty()) {
      return '';
    }

    let current = this.dll.getHead();
    let objString = '';
    while(current){
      objString = current.element + ' ' + objString;
      current = current.next;
    }

    return objString.trim();
  }  
}
Input:
let deque = new dequeWithDLL();
deque.insertBack(5);
deque.insertBack(10);
console.log(deque.getBack());
deque.removeBack();
console.log(deque.getBack());
deque.insertFront(15);
console.log(deque.getFront());
deque.removeFront(); 
console.log(deque.getFront());
console.log(deque.toString());

Output:
5
5
15
"15"

Time Complexity

# Access Search Insert Delete
Average Θ(1) Θ(N) Θ(1) Θ(1)
Worst O(1) O(N) O(1) O(1)

Space Complexity

# space
Worst O(N)