Open In App

Doubly Linked List in C++

Last Updated : 02 Jun, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A Doubly Linked List (DLL) is a two-way list in which each node has two pointers, the next and previous that have reference to both the next node and previous node respectively. Unlike a singly linked list where each node only points to the next node, a doubly linked list has an extra previous pointer that allows traversal in both the forward and backward directions.

In this article, we will learn about the doubly linked list representation, implementation of doubly linked list in C++, basic operations that can be performed on doubly linked list, its advantages and disadvantages.

Doubly Linked List Representation in C++

In a doubly linked list, two pointers are maintained to keep track of the list i.e. head (that points to the first node) and tail (that points to the last node).

DLL1
Doubly Linked List

Implementation of Doubly Linked List in C++

To implement all the basic operations that can be performed on a doubly linked list, we need to first define a node. Let's see how we can create a new node in a doubly linked list.

Creating a Node in Doubly Linked List in C++

NodeDoublyLinkedList-(1)
Node-Doubly Linked List

Each node of a doubly linked list (DLL) consists of three fields:

  • Item or Data: It is the value stored in the node.
  • Next: A reference to the next node in the list.
  • Previous: A reference to the last node in the list.

In C++, a node of a doubly linked list can be created using the below format:

class Node
{
    public:
    int data;
    Node *next;
    Node *prev;
};

Basic Operations on C++ Doubly Linked List

We can perform the following basic operations on a doubly linked list:

OperationDescriptionTime ComplexitySpace Complexity
Insertion at BeginningThis function is used to insert a new node at the beginning of the DLL.O(1)O(1)
Insertion at EndThis function is used to insert a new node at the end of the DLL.O(1)O(1)
Insertion at Specific PositionThis function is used to insert a new node at a specific position in the DLL.
O(n)

O(1)
Deletion from BeginningThis function is used to delete a node at the beginning of the DLL.O(1)O(1)
Deletion from EndThis function is used to delete a node at the end of the DLL.O(1)O(1)
Deletion of Specific NodeThis function is used to delete a node from a specific position of the DLL.
 

O(n)

O(1)
Forward TraversalThis function is used for traversing in a forward direction in a DLL.O(n)O(1)
Reverse TraversalThis function is used for traversing in a reverse direction in a DLL.O(n)O(1)

1. Insertion in Doubly Linked List in C++

In a doubly linked list, there are three ways in which the insertion operation can be performed:

  • Insertion at the beginning of DLL
  • Insertion at the end of DLL
  • Insertion at Specific Position in DLL

a. Insertion at the Beginning in Doubly Linked List

Insertion_beginning_Doubly-Linked-List
Insertion at Beginning- Doubly Linked List

First, create a new node to be inserted and then follow the below approach to insert a new node at the beginning of a doubly linked list:

Approach:

  • First, create a newNode
  • If the list is empty:
    • set newNode->next to NULL.
    • set newNode->prev to NULL.
    • point the head pointer to newNode.
  • If the list is not empty:
    • set newNode->next to head.
    • set newNode->prev to NULL.
    • set head->prev to newNode.
    • point the head pointer to newNode.

b. Insertion at the End in Doubly Linked List

Insertion_end_Doubly-Linked-List
Insertion at End- Doubly Linked List

First, create a new node to be inserted and then follow the below approach to insert a new node at the end of a doubly linked list:

Approach:

  • First, create a newNode.
  • If the list is empty:
    • set newNode->next to NULL.
    • set newNode->prev to NULL.
    • point the head pointer to newNode.
  • If the list is not empty:
    • find the last node by iterating the list (i.e. where last->next == NULL).
    • set last->next to newNode.
    • set newNode->prev to last.
    • set newNode->next to NULL.

c. Insertion at Specific Position in Doubly Linked List

Insertion_middle_Doubly-Linked-List
Insertion at Specific Position- Doubly Linked List

First, create a new node to be inserted and then follow the below approach to insert a new node at a given position in a doubly linked list:

Approach:

  • First, create a newNode.
  • Check whether the given position is valid or not by finding the size of the list.
  • If the given position is 0 (or 1 depending on indexing):
    • we can use the insertion at the beginning approach only.
  • If the given position is the last i.e. it is equal to the size of the list:
    • we can use the insertion at the end approach here.
  • If the given position is valid then do the following:
    • start traversing the list to find the node that comes immediately before the given position (call it prevNode).
    • set newNode->next to prevNode->next.
    • set newNode->prev to prevNode.
    • if prevNode->next is not NULL, set prevNode->next->prev to newNode.
    • set prevNode->next to newNode.

2. Deletion in Doubly Linked List in C++

Like insertion, there are three ways in which the deletion operation can be performed:

  • Deletion at the beginning of DLL
  • Deletion at the end of DLL
  • Deletion at Specific Position in DLL

a. Deletion from the Beginning of Doubly Linked List

Deletion_beginning_DLL
Deletion from Beginning- Doubly Linked List

To delete a node from the beginning of the doubly linked list, follow the below approach:

Approach:

  • First, check if the list is empty or not, if the list is empty then there's nothing to delete.
  • if the list have only one node then:
    • set head to NULL.
    • free the memory of the node.
  • if the list have more than one node:
    • update the head by pointing it to head->next.
    • set the prev of the new head to NULL.
    • free the memory of the old head.

b. Deletion from the End of Doubly Linked List

Deletion_end_DLL
Deletion from End- Doubly Linked List

To delete a node from the end of a doubly linked list, follow the below approach:

Approach:

  • First, check if the list is empty or not, if the list is empty there is nothing to delete.
  • If the list is not empty then do the following:
    • Find the last node by iterating through the list (i.e. where last->next == NULL).
    • Then, check if the last node is the only node (head->next == NULL):
      • just update the head to NULL.
    • If more than one node:
      • set the next of the second last node (last->prev) to NULL.
    • Finally, free the memory of the last node.

c. Deletion From Specific Position of Doubly Linked List

Deletion_specificNode_DLL
Deletion from specific position- Doubly Linked List

To delete a node from a specific position in a doubly linked list, follow the below approach:

Approach:

  • If the given position is 0 (or 1 according to indexing), we can use deletion at the beginning.
  • If the position is the last position, we can use deletion at the end.
  • Check whether the given position is valid or not:
  • If the given position is valid do the following:
    • Start traversing the list to find the node to be deleted (delNode).
    • If delNode is the first node, adjust the head.
    • If not, point the delNode->prev->next to the next node (delNode->next) and delNode->next->prev to the previous node (delNode->prev).
    • Finally, free the memory of the last node. node to be deleted.

3. Traversal in a Doubly Linked List in C++

Traversing a doubly linked list means iterating through the list by visiting each node and performing the desired operations. This can be done by maintaining a temp variable that starts from the head of the doubly linked list and follows the next pointer for traversing until the end of the list. In a doubly linked list, we can traverse in both directions:

  • In forward traversal, traverse from the head to the tail node.
  • In reverse traversal, traverse from the tail to the head node.

a. Forward Traversal in Doubly Linked List

To traverse the doubly linked list in the forward direction, follow the below approach:

Approach:

  • First, create a temp pointer and copy the head pointer to it (temp = head).
  • For traversing in a forward direction keep moving temp to temp -> next.
  • We can perform the desired operation in each iteration.

b. Reverse Traversal in Doubly in Doubly Linked List

To traverse the doubly linked list in the reverse direction, follow the below approach:

Approach:

  • First, create a temp pointer and copy the tail pointer to it. (temp = tail).
  • For traversing in a backward direction keep moving the temp pointer to temp -> prev.
  • We can perform the desired operation in each iteration.

C++ Program to Implement Doubly Linked List

The below program demonstrates the implementation of all the basic operations on the doubly linked list.

C++
// C++ program to Implement doubly linked list

#include <iostream>
using namespace std;

// Define a class named Node to represent a node in the
// doubly linked list.
class Node {
public:
    // Data part of the node.
    int data;
    // Pointer to the next node.
    Node* next;
    // Pointer to the previous node.
    Node* prev;

    // Constructor to initialize the node with given data.
    Node(int data)
    {
        this->data = data;
        this->next = nullptr;
        this->prev = nullptr;
    }
};

// Function to insert a node at the beginning of the doubly
// linked list.
void insertAtBeginning(Node*& head, int data)
{
    // Create a new node with the given data.
    Node* newNode = new Node(data);

    // Check if the doubly linked list is empty.
    if (head == nullptr) {
        head = newNode;
        return;
    }

    // Update the next and previous pointers to insert the
    // new node at the beginning.
    newNode->next = head;
    head->prev = newNode;
    head = newNode;
}

// Function to insert a node at the end of the doubly linked
// list.
void insertAtEnd(Node*& head, int data)
{
    // Create a new node with the given data.
    Node* newNode = new Node(data);

    // Check if the doubly linked list is empty.
    if (head == nullptr) {
        head = newNode;
        return;
    }

    // Traverse to the last node of the list.
    Node* temp = head;
    while (temp->next != nullptr) {
        temp = temp->next;
    }

    // Update the next and previous pointers to insert the
    // new node at the end.
    temp->next = newNode;
    newNode->prev = temp;
}

// Function to insert a node at a specified position in the
// doubly linked list.
void insertAtPosition(Node*& head, int data, int position)
{
    if (position < 1) {
        cout << "Position should be >= 1." << endl;
        return;
    }

    // If inserting at the head position.
    if (position == 1) {
        insertAtBeginning(head, data);
        return;
    }

    // Create a new node with the given data.
    Node* newNode = new Node(data);
    Node* temp = head;

    // Traverse to the node before the specified position.
    for (int i = 1; temp != nullptr && i < position - 1;
         i++) {
        temp = temp->next;
    }

    // Check if the position is greater than the number of
    // nodes.
    if (temp == nullptr) {
        cout << "Position greater than the number of nodes."
             << endl;
        return;
    }

    // Update the next and previous pointers to insert the
    // new node at the specified position.
    newNode->next = temp->next;
    newNode->prev = temp;
    if (temp->next != nullptr) {
        temp->next->prev = newNode;
    }
    temp->next = newNode;
}

// Function to delete a node from the beginning of the
// doubly linked list.
void deleteAtBeginning(Node*& head)
{
    // Check if the doubly linked list is empty.
    if (head == nullptr) {
        cout << "The list is already empty." << endl;
        return;
    }

    // Update the head pointer and delete the first node.
    Node* temp = head;
    head = head->next;
    if (head != nullptr) {
        head->prev = nullptr;
    }
    delete temp;
}

// Function to delete a node from the end of the doubly
// linked list.
void deleteAtEnd(Node*& head)
{
    // Check if the doubly linked list is empty.
    if (head == nullptr) {
        cout << "The list is already empty." << endl;
        return;
    }

    Node* temp = head;
    // If there is only one node in the list.
    if (temp->next == nullptr) {
        head = nullptr;
        delete temp;
        return;
    }

    // Traverse to the last node of the list.
    while (temp->next != nullptr) {
        temp = temp->next;
    }

    // Update the previous pointer of the second last node
    // and delete the last node.
    temp->prev->next = nullptr;
    delete temp;
}

// Function to delete a node from a specified position in
// the doubly linked list.
void deleteAtPosition(Node*& head, int position)
{
    // Check if the doubly linked list is empty.
    if (head == nullptr) {
        cout << "The list is already empty." << endl;
        return;
    }

    // If deleting the head node.
    if (position == 1) {
        deleteAtBeginning(head);
        return;
    }

    Node* temp = head;
    // Traverse to the node at the specified position.
    for (int i = 1; temp != nullptr && i < position; i++) {
        temp = temp->next;
    }

    // Check if the position is greater than the number of
    // nodes.
    if (temp == nullptr) {
        cout << "Position is greater than the number of "
                "nodes."
             << endl;
        return;
    }

    // Update the next and previous pointers and delete the
    // node at the specified position.
    if (temp->next != nullptr) {
        temp->next->prev = temp->prev;
    }
    if (temp->prev != nullptr) {
        temp->prev->next = temp->next;
    }
    delete temp;
}

// Function to print the doubly linked list in forward
// direction.
void printListForward(Node* head)
{
    Node* temp = head;
    cout << "Forward List: ";
    while (temp != nullptr) {
        cout << temp->data << " ";
        temp = temp->next;
    }
    cout << endl;
}

// Function to print the doubly linked list in reverse
// direction.
void printListReverse(Node* head)
{
    Node* temp = head;
    if (temp == nullptr) {
        cout << "The list is empty." << endl;
        return;
    }

    // Move to the end of the list.
    while (temp->next != nullptr) {
        temp = temp->next;
    }

    // Traverse backwards.
    cout << "Reverse List: ";
    while (temp != nullptr) {
        cout << temp->data << " ";
        temp = temp->prev;
    }
    cout << endl;
}

int main()
{
    Node* head = nullptr;

    // Demonstrating various operations on the doubly linked
    // list.
    // Insertion at End
    insertAtEnd(head, 10);
    insertAtEnd(head, 20);
    // Insertion at beginning
    insertAtBeginning(head, 5);
    // Insertion at specific position
    insertAtPosition(head, 15, 2);

    // print the list
    cout << "After Insertions:" << endl;
    printListForward(head);
    printListReverse(head);

    // deletion from beginning
    deleteAtBeginning(head);
    // deletion from end
    deleteAtEnd(head);
    // deletion from specific position
    deleteAtPosition(head, 2);

    cout << "After Deletions:" << endl;
    printListForward(head);

    return 0;
}

Output
After Insertions:
Forward List: 5 15 10 20 
Reverse List: 20 10 15 5 
After Deletions:
Forward List: 15 

Advantages of Doubly Linked List in C++

The following are the advantages of a doubly linked list in C++:

  • The doubly linked list allows us to traverse in both forward and backward directions.
  • The deletion of a node is more efficient and easy as it has a pointer to the previous node.
  • It is easier to perform the reverse operation.
  • A doubly linked list is dynamic in nature so it can grow or shrink in size.

Disadvantages of Doubly Linked List in C++

  • It requires more memory than arrays, per node due to the additional storage used by the pointers.
  • It is more complex to implement and maintain as compared to the singly-linked list.
  • We have to traverse from the head node to the specific node for insertion and deletion at specific positions.

Next Article
Article Tags :
Practice Tags :

Similar Reads