Open In App

Implementation of Deque using doubly linked list

Last Updated : 12 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

A Deque (Double-Ended Queue) is a data structure that allows adding and removing elements from both the front and rear ends. Using a doubly linked list to implement a deque makes these operations very efficient, as each node in the list has pointers to both the previous and next nodes. This means we can insert and delete elements from both ends in constant time.

Operations on Deque

The following four basic operations are typically performed on a deque:

  • insertFront(): Adds an item at the front of the deque.
  • insertRear(): Adds an item at the rear of the deque.
  • deleteFront(): Removes an item from the front of the deque.
  • deleteRear(): Removes an item from the rear of the deque.

Additionally, the following operations are also supported:

  • getFront(): Retrieves the front item from the deque.
  • getRear(): Retrieves the last item from the deque.
  • isEmpty(): Checks if the deque is empty.
  • size(): Returns the number of elements in the deque.
  • erase(): Removes all elements from the deque.
deque-using-ll

Deque using Linked List

Doubly Linked List Representation of Deque

For implementing deque, we need to keep track of two pointers, front and rear. We enqueue (push) an item at the rear or the front end of deque and dequeue(pop) an item from both rear and front end.

Working

Declare two pointers front and rear of type Node, where Node represents the structure of a node of a doubly linked list. Initialize both of them with value NULL.

Insertion at Front end

1. Allocate space for a newNode of doubly linked list.
2. IF newNode == NULL, then
3. print “Overflow”
4. ELSE
5. IF front == NULL, then
6. rear = front = newNode
7. ELSE
8. newNode->next = front
9. front->prev = newNode
10. front = newNode

Insertion at Rear end

1. Allocate space for a newNode of doubly linked list.
2. IF newNode == NULL, then
3. print “Overflow”
4. ELSE
5. IF rear == NULL, then
6. front = rear = newNode
7. ELSE
8. newNode->prev = rear
9. rear->next = newNode
10. rear = newNode

Deletion from Front end

1. IF front == NULL
2. print “Underflow”
3. ELSE
4. Initialize temp = front
5. front = front->next
6. IF front == NULL
7. rear = NULL
8. ELSE
9. front->prev = NULL
10 Deallocate space for temp

Deletion from Rear end

1. IF front == NULL
2. print “Underflow”
3. ELSE
4. Initialize temp = rear
5. rear = rear->prev
6. IF rear == NULL
7. front = NULL
8. ELSE
9. rear->next = NULL
10 Deallocate space for temp

C++
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node *prev, *next;
    Node(int data) { 
        this->data = data; 
        prev = nullptr; 
        next = nullptr; 
    }
};

class Deque {
    Node *front, *rear;
    int size;
public:
    Deque() { front = nullptr; rear = nullptr; size = 0; }

    bool isEmpty() { return front == nullptr; }
    int getSize() { return size; }

    void insertFront(int data) {
        Node* newNode = new Node(data);
        if (isEmpty()) front = rear = newNode;
        else {
            newNode->next = front;
            front->prev = newNode;
            front = newNode;
        }
        size++;
    }

    void insertRear(int data) {
        Node* newNode = new Node(data);
        if (isEmpty()) front = rear = newNode;
        else {
            newNode->prev = rear;
            rear->next = newNode;
            rear = newNode;
        }
        size++;
    }

    void deleteFront() {
        if (isEmpty()) cout << "UnderFlow\n";
        else {
            Node* temp = front;
            front = front->next;
            if (front) front->prev = nullptr;
            else rear = nullptr;
            delete temp;
            size--;
        }
    }

    void deleteRear() {
        if (isEmpty()) cout << "UnderFlow\n";
        else {
            Node* temp = rear;
            rear = rear->prev;
            if (rear) rear->next = nullptr;
            else front = nullptr;
            delete temp;
            size--;
        }
    }

    int getFront() { return isEmpty() ? -1 : front->data; }
    int getRear() { return isEmpty() ? -1 : rear->data; }

    void clear() {
        while (!isEmpty()) deleteFront();
    }
};

int main() {
    Deque dq;
    dq.insertRear(5);
    dq.insertRear(10);
    cout << "Rear: " << dq.getRear() << endl;
    dq.deleteRear();
    cout << "New Rear: " << dq.getRear() << endl;

    dq.insertFront(15);
    cout << "Front: " << dq.getFront() << endl;
    cout << "Size: " << dq.getSize() << endl;

    dq.deleteFront();
    cout << "New Front: " << dq.getFront() << endl;

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node *prev, *next;
};

struct Deque {
    struct Node *front, *rear;
    int size;
};

struct Deque* createDeque() {
    struct Deque* dq = (struct Deque*)malloc(sizeof(struct Deque));
    dq->front = dq->rear = NULL;
    dq->size = 0;
    return dq;
}

int isEmpty(struct Deque* dq) { return dq->front == NULL; }
int getSize(struct Deque* dq) { return dq->size; }

void insertFront(struct Deque* dq, int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = dq->front;
    if (isEmpty(dq)) dq->front = dq->rear = newNode;
    else {
        dq->front->prev = newNode;
        dq->front = newNode;
    }
    dq->size++;
}

void insertRear(struct Deque* dq, int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    if (isEmpty(dq)) dq->front = dq->rear = newNode;
    else {
        newNode->prev = dq->rear;
        dq->rear->next = newNode;
        dq->rear = newNode;
    }
    dq->size++;
}

void deleteFront(struct Deque* dq) {
    if (isEmpty(dq)) printf("UnderFlow\n");
    else {
        struct Node* temp = dq->front;
        dq->front = dq->front->next;
        if (dq->front) dq->front->prev = NULL;
        else dq->rear = NULL;
        free(temp);
        dq->size--;
    }
}

void deleteRear(struct Deque* dq) {
    if (isEmpty(dq)) printf("UnderFlow\n");
    else {
        struct Node* temp = dq->rear;
        dq->rear = dq->rear->prev;
        if (dq->rear) dq->rear->next = NULL;
        else dq->front = NULL;
        free(temp);
        dq->size--;
    }
}

int getFront(struct Deque* dq) { return isEmpty(dq) ? -1 : dq->front->data; }
int getRear(struct Deque* dq) { return isEmpty(dq) ? -1 : dq->rear->data; }

void clear(struct Deque* dq) {
    while (!isEmpty(dq)) deleteFront(dq);
}

int main() {
    struct Deque* dq = createDeque();
    insertRear(dq, 5);
    insertRear(dq, 10);
    printf("Rear: %d\n", getRear(dq));
    deleteRear(dq);
    printf("New Rear: %d\n", getRear(dq));

    insertFront(dq, 15);
    printf("Front: %d\n", getFront(dq));
    printf("Size: %d\n", getSize(dq));

    deleteFront(dq);
    printf("New Front: %d\n", getFront(dq));

    clear(dq);
    free(dq);
    return 0;
}
Java
import java.util.LinkedList;
import java.util.Deque;

public class DequeExample {
    private LinkedList<Integer> deque;

    public DequeExample() {
        deque = new LinkedList<>();
    }

    public boolean isEmpty() { return deque.isEmpty(); }
    public int getSize() { return deque.size(); }

    public void insertFront(int data) {
        deque.addFirst(data);
    }

    public void insertRear(int data) {
        deque.addLast(data);
    }

    public void deleteFront() {
        if (isEmpty()) System.out.println("UnderFlow");
        else deque.removeFirst();
    }

    public void deleteRear() {
        if (isEmpty()) System.out.println("UnderFlow");
        else deque.removeLast();
    }

    public int getFront() { return isEmpty() ? -1 : deque.getFirst(); }
    public int getRear() { return isEmpty() ? -1 : deque.getLast(); }

    public void clear() { deque.clear(); }

    public static void main(String[] args) {
        DequeExample dq = new DequeExample();
        dq.insertRear(5);
        dq.insertRear(10);
        System.out.println("Rear: " + dq.getRear());
        dq.deleteRear();
        System.out.println("New Rear: " + dq.getRear());

        dq.insertFront(15);
        System.out.println("Front: " + dq.getFront());
        System.out.println("Size: " + dq.getSize());

        dq.deleteFront();
        System.out.println("New Front: " + dq.getFront());
    }
}
Python
# Deque implementation in Python
class Node:
    def __init__(self, data):
        self.data = data
        self.prev = None
        self.next = None

class Deque:
    def __init__(self):
        self.front = None
        self.rear = None
        self.size = 0

    def is_empty(self):
        return self.front is None

    def get_size(self):
        return self.size

    def insert_front(self, data):
        new_node = Node(data)
        if self.is_empty():
            self.front = self.rear = new_node
        else:
            new_node.next = self.front
            self.front.prev = new_node
            self.front = new_node
        self.size += 1

    def insert_rear(self, data):
        new_node = Node(data)
        if self.is_empty():
            self.front = self.rear = new_node
        else:
            new_node.prev = self.rear
            self.rear.next = new_node
            self.rear = new_node
        self.size += 1

    def delete_front(self):
        if self.is_empty():
            print("UnderFlow")
        else:
            temp = self.front
            self.front = self.front.next
            if self.front:
                self.front.prev = None
            else:
                self.rear = None
            del temp
            self.size -= 1

    def delete_rear(self):
        if self.is_empty():
            print("UnderFlow")
        else:
            temp = self.rear
            self.rear = self.rear.prev
            if self.rear:
                self.rear.next = None
            else:
                self.front = None
            del temp
            self.size -= 1

    def get_front(self):
        return -1 if self.is_empty() else self.front.data

    def get_rear(self):
        return -1 if self.is_empty() else self.rear.data

    def clear(self):
        while not self.is_empty():
            self.delete_front()

# Example usage
if __name__ == '__main__':
    dq = Deque()
    dq.insert_rear(5)
    dq.insert_rear(10)
    print("Rear:", dq.get_rear())
    dq.delete_rear()
    print("New Rear:", dq.get_rear())

    dq.insert_front(15)
    print("Front:", dq.get_front())
    print("Size:", dq.get_size())

    dq.delete_front()
    print("New Front:", dq.get_front())
C#
// Deque implementation in C#
using System;

public class Node {
    public int data;
    public Node prev, next;
    public Node(int data) {
        this.data = data;
        this.prev = null;
        this.next = null;
    }
}

public class Deque {
    private Node front, rear;
    private int size;

    public Deque() {
        front = rear = null;
        size = 0;
    }

    public bool IsEmpty() {
        return front == null;
    }

    public int GetSize() {
        return size;
    }

    public void InsertFront(int data) {
        Node newNode = new Node(data);
        if (IsEmpty()) front = rear = newNode;
        else {
            newNode.next = front;
            front.prev = newNode;
            front = newNode;
        }
        size++;
    }

    public void InsertRear(int data) {
        Node newNode = new Node(data);
        if (IsEmpty()) front = rear = newNode;
        else {
            newNode.prev = rear;
            rear.next = newNode;
            rear = newNode;
        }
        size++;
    }

    public void DeleteFront() {
        if (IsEmpty()) Console.WriteLine("UnderFlow");
        else {
            Node temp = front;
            front = front.next;
            if (front != null) front.prev = null;
            else rear = null;
            temp = null;
            size--;
        }
    }

    public void DeleteRear() {
        if (IsEmpty()) Console.WriteLine("UnderFlow");
        else {
            Node temp = rear;
            rear = rear.prev;
            if (rear != null) rear.next = null;
            else front = null;
            temp = null;
            size--;
        }
    }

    public int GetFront() {
        return IsEmpty() ? -1 : front.data;
    }

    public int GetRear() {
        return IsEmpty() ? -1 : rear.data;
    }

    public void Clear() {
        while (!IsEmpty()) DeleteFront();
    }
}

class Program {
    static void Main() {
        Deque dq = new Deque();
        dq.InsertRear(5);
        dq.InsertRear(10);
        Console.WriteLine("Rear: " + dq.GetRear());
        dq.DeleteRear();
        Console.WriteLine("New Rear: " + dq.GetRear());

        dq.InsertFront(15);
        Console.WriteLine("Front: " + dq.GetFront());
        Console.WriteLine("Size: " + dq.GetSize());

        dq.DeleteFront();
        Console.WriteLine("New Front: " + dq.GetFront());
    }
}
JavaScript
class Node {
    constructor(data) {
        this.data = data;
        this.prev = null;
        this.next = null;
    }
}

class Deque {
    constructor() {
        this.front = null;
        this.rear = null;
        this.size = 0;
    }

    isEmpty() {
        return this.front === null;
    }

    getSize() {
        return this.size;
    }

    insertFront(data) {
        const newNode = new Node(data);
        if (this.isEmpty()) {
            this.front = this.rear = newNode;
        } else {
            newNode.next = this.front;
            this.front.prev = newNode;
            this.front = newNode;
        }
        this.size++;
    }

    insertRear(data) {
        const newNode = new Node(data);
        if (this.isEmpty()) {
            this.front = this.rear = newNode;
        } else {
            newNode.prev = this.rear;
            this.rear.next = newNode;
            this.rear = newNode;
        }
        this.size++;
    }

    deleteFront() {
        if (this.isEmpty()) console.log("UnderFlow");
        else {
            const temp = this.front;
            this.front = this.front.next;
            if (this.front) this.front.prev = null;
            else this.rear = null;
            this.size--;
        }
    }

    deleteRear() {
        if (this.isEmpty()) console.log("UnderFlow");
        else {
            const temp = this.rear;
            this.rear = this.rear.prev;
            if (this.rear) this.rear.next = null;
            else this.front = null;
            this.size--;
        }
    }

    getFront() {
        return this.isEmpty() ? -1 : this.front.data;
    }

    getRear() {
        return this.isEmpty() ? -1 : this.rear.data;
    }

    clear() {
        while (!this.isEmpty()) this.deleteFront();
    }
}

// Driver code
const dq = new Deque();
dq.insertRear(5);
dq.insertRear(10);
console.log("Rear:", dq.getRear());
dq.deleteRear();
console.log("New Rear:", dq.getRear());

dq.insertFront(15);
console.log("Front:", dq.getFront());
console.log("Size:", dq.getSize());

dq.deleteFront();
console.log("New Front:", dq.getFront());

Output
Rear: 10
New Rear: 5
Front: 15
Size: 2
New Front: 5
  • Time Complexity : Time complexity of operations like insertFront(), insertRear(), deleteFront(), deleteRear() is O(1). The Time Complexity of erase() is O(n).
  • Auxiliary space: O(1)


Next Article
Article Tags :
Practice Tags :

Similar Reads