Open In App

Doubly Linked List Tutorial

Last Updated : 28 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

A doubly linked list is a more complex data structure than a singly linked list, but it offers several advantages. The main advantage of a doubly linked list is that it allows for efficient traversal of the list in both directions. This is because each node in the list contains a pointer to the previous node and a pointer to the next node. This allows for quick and easy insertion and deletion of nodes from the list, as well as efficient traversal of the list in both directions.

Doubly-Linked-List-in-Data-Structure

Doubly Linked List in Data Structure

What is a Doubly Linked List?

A doubly linked list is a data structure that consists of a set of nodes, each of which contains a value and two pointers, one pointing to the previous node in the list and one pointing to the next node in the list. This allows for efficient traversal of the list in both directions, making it suitable for applications where frequent insertions and deletions are required.

Representation of Doubly Linked List in Data Structure:

In a data structure, a doubly linked list is represented using nodes that have three fields:

  1. Data
  2. A pointer to the next node (next)
  3. A pointer to the previous node (prev).

Node Definition:

Here is how a node in a Doubly Linked List is typically represented:

C++
struct Node {

    // To store the Value or data.
    int data;

    // Pointer to point the Previous Element
    Node* prev;

    // Pointer to point the Next Element
    Node* next;
};

Each node in a Doubly Linked List contains the data it holds, a pointer to the next node in the list, and a pointer to the previous node in the list. By linking these nodes together through the next and prev pointers, we can traverse the list in both directions (forward and backward), which is a key feature of a Doubly Linked List.

Operations on Doubly Linked List:

  • Traversal in Doubly Linked List
  • Searching in Doubly Linked List
  • Finding Length of Doubly Linked List
  • Insertion in Doubly Linked List:
    • Insertion at the beginning of Doubly Linked List
    • Insertion at the end of the Doubly Linked List
    • Insertion at a specific position in Doubly Linked List
  • Deletion in Doubly Linked List:
    • Deletion of a node at the beginning of Doubly Linked List
    • Deletion of a node at the end of Doubly Linked List
    • Deletion of a node at a specific position in Doubly Linked List

Let’s go through each of the operations mentioned above, one by one.

Traversal in Doubly Linked List:

To Traverse the doubly list, we can use the following steps:

a. Forward Traversal:

  • Initialize a pointer to the head of the linked list.
  • While the pointer is not null:
  • Visit the data at the current node.
  • Move the pointer to the next node.

b. Backward Traversal:

  • Initialize a pointer to the tail of the linked list.
  • While the pointer is not null:
  • Visit the data at the current node.
  • Move the pointer to the previous node.

Below are the implementation of the above approach:

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

// Define the Node structure
struct Node {
    int data; // Data stored in the node
    Node* next; // Pointer to the next node in the list
    Node* prev; // Pointer to the previous node in the list

    // Constructor to initialize Node with data
    Node(int data) : data(data), next(nullptr), prev(nullptr) {}
};

// Function to traverse the doubly linked list in forward direction
void forwardTraversal(Node* head) {
    // Start traversal from the head of the list
    Node* current = head;

    // Continue until current node is not null (end of list)
    while (current != nullptr) {
        // Output data of the current node
        cout << current->data << " ";

        // Move to the next node
        current = current->next;
    }

    // Print newline after traversal
    cout << endl;
}

// Function to traverse the doubly linked list in backward direction
void backwardTraversal(Node* tail) {
    // Start traversal from the tail of the list
    Node* current = tail;

    // Continue until current node is not null (end of list)
    while (current != nullptr) {
        // Output data of the current node
        cout << current->data << " ";

        // Move to the previous node
        current = current->prev;
    }

    // Print newline after traversal
    cout << endl;
}

int main() {
    // Sample usage of the doubly linked list and traversal functions
    Node* head = new Node(1);
    Node* second = new Node(2);
    Node* third = new Node(3);

    head->next = second;
    second->prev = head;
    second->next = third;
    third->prev = second;

    cout << "Forward Traversal:" << endl;
    forwardTraversal(head);

    cout << "Backward Traversal:" << endl;
    backwardTraversal(third);

    // Free memory allocated for nodes
    delete head;
    delete second;
    delete third;

    return 0;
}
Java
class Node {
    int data;
    Node next;
    Node prev;

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

public class DoublyLinkedListTraversal {

    // Function to traverse the doubly linked list in forward direction
    static void forwardTraversal(Node head) {
        // Start traversal from the head of the list
        Node current = head;

        // Continue until the current node is not null (end of the list)
        while (current != null) {
            // Output data of the current node
            System.out.print(current.data + " ");

            // Move to the next node
            current = current.next;
        }

        // Print newline after traversal
        System.out.println();
    }

    // Function to traverse the doubly linked list in backward direction
    static void backwardTraversal(Node tail) {
        // Start traversal from the tail of the list
        Node current = tail;

        // Continue until the current node is not null (end of the list)
        while (current != null) {
            // Output data of the current node
            System.out.print(current.data + " ");

            // Move to the previous node
            current = current.prev;
        }

        // Print newline after traversal
        System.out.println();
    }

    public static void main(String[] args) {
        // Sample usage of the doubly linked list and traversal functions
        Node head = new Node(1);
        Node second = new Node(2);
        Node third = new Node(3);

        head.next = second;
        second.prev = head;
        second.next = third;
        third.prev = second;

        System.out.println("Forward Traversal:");
        forwardTraversal(head);

        System.out.println("Backward Traversal:");
        backwardTraversal(third);
    }
}
Python3
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None
        self.prev = None

# Function to traverse the doubly linked list in forward direction
def forward_traversal(head):
    # Start traversal from the head of the list
    current = head

    # Continue until the current node is not None (end of the list)
    while current is not None:
        # Output data of the current node
        print(current.data, end=" ")

        # Move to the next node
        current = current.next

    # Print newline after traversal
    print()

# Function to traverse the doubly linked list in backward direction
def backward_traversal(tail):
    # Start traversal from the tail of the list
    current = tail

    # Continue until the current node is not None (end of the list)
    while current is not None:
        # Output data of the current node
        print(current.data, end=" ")

        # Move to the previous node
        current = current.prev

    # Print newline after traversal
    print()

# Sample usage of the doubly linked list and traversal functions
head = Node(1)
second = Node(2)
third = Node(3)

head.next = second
second.prev = head
second.next = third
third.prev = second

print("Forward Traversal:")
forward_traversal(head)

print("Backward Traversal:")
backward_traversal(third)
JavaScript
class Node {
    constructor(data) {
        this.data = data;
        this.next = null;
        this.prev = null;
    }
}

// Function to traverse the doubly linked list in forward direction
function forwardTraversal(head) {
    // Start traversal from the head of the list
    let current = head;

    // Continue until the current node is not null (end of the list)
    while (current !== null) {
        // Output data of the current node
        process.stdout.write(current.data + " ");

        // Move to the next node
        current = current.next;
    }

    // Print newline after traversal
    console.log();
}

// Function to traverse the doubly linked list in backward direction
function backwardTraversal(tail) {
    // Start traversal from the tail of the list
    let current = tail;

    // Continue until the current node is not null (end of the list)
    while (current !== null) {
        // Output data of the current node
        process.stdout.write(current.data + " ");

        // Move to the previous node
        current = current.prev;
    }

    // Print newline after traversal
    console.log();
}

// Sample usage of the doubly linked list and traversal functions
let head = new Node(1);
let second = new Node(2);
let third = new Node(3);

head.next = second;
second.prev = head;
second.next = third;
third.prev = second;

console.log("Forward Traversal:");
forwardTraversal(head);

console.log("Backward Traversal:");
backwardTraversal(third);

Finding Length of Doubly Linked List:

To find the length of doubly list, we can use the following steps:

  • Start at the head of the list.
  • Traverse through the list, counting each node visited.
  • Return the total count of nodes as the length of the list.

Below are the implementation of the above approach:

C++
// Node structure for doubly linked list
struct Node {
    int data; // Data stored in the node
    Node* prev; // Pointer to the previous node
    Node* next; // Pointer to the next node

    // Constructor to initialize node with given value
    Node(int val)
        : data(val)
        , prev(nullptr)
        , next(nullptr)
    {
    }
};

// Function to find the length of a doubly linked list
int findLength(Node* head)
{
    // Variable to store the length of the list
    int length = 0;

    // Pointer to traverse the list
    Node* current = head;

    // Traverse the list until reaching the end
    while (current != nullptr) {
        // Increment length for each node visited
        length++;

        // Move to the next node
        current = current->next;
    }
    // Return the length of the list
    return length;
}
Java
// Node structure for doubly linked list
class Node {
    constructor(data) {
        this.data = data; // Data stored in the node
        this.prev = null; // Pointer to the previous node
        this.next = null; // Pointer to the next node
    }
}

// Function to find the length of a doubly linked list
function findLength(head) {
    let length = 0; // Variable to store the length of the list
    let current = head; // Pointer to traverse the list

    // Traverse the list until reaching the end
    while (current !== null) {
        length++; // Increment length for each node visited
        current = current.next; // Move to the next node
    }

    return length; // Return the length of the list
}
Python3
# Node class for doubly linked list
class Node:
    def __init__(self, val):
        # Data stored in the node
        self.data = val
        # Pointer to the previous node
        self.prev = None
        # Pointer to the next node
        self.next = None

# Function to find the length of a doubly linked list
def find_length(head):
    # Variable to store the length of the list
    length = 0

    # Pointer to traverse the list
    current = head

    # Traverse the list until reaching the end
    while current is not None:
        # Increment length for each node visited
        length += 1

        # Move to the next node
        current = current.next
    
    # Return the length of the list
    return length
JavaScript
// Node class for doubly linked list
class Node {
    constructor(val) {
        this.data = val; // Data stored in the node
        this.prev = null; // Pointer to the previous node
        this.next = null; // Pointer to the next node
    }
}

// Function to find the length of a doubly linked list
function findLength(head) {
    // Variable to store the length of the list
    let length = 0;

    // Pointer to traverse the list
    let current = head;

    // Traverse the list until reaching the end
    while (current !== null) {
        // Increment length for each node visited
        length++;

        // Move to the next node
        current = current.next;
    }

    // Return the length of the list
    return length;
}

Insertion at the Beginning in Doubly Linked List:

Insertion_at_beginning_Doubly-Linked-List

Insertion at the Beginning in Doubly Linked List

To insert a new node at the beginning of the doubly list, we can use the following steps:

  • Allocate memory for a new node and assign the provided value to its data field.
  • Set the previous pointer of the new node to nullptr.
  • If the list is empty:
    • Set the next pointer of the new node to nullptr.
    • Update the head pointer to point to the new node.
  • If the list is not empty:
    • Set the next pointer of the new node to the current head.
    • Update the previous pointer of the current head to point to the new node.
    • Update the head pointer to point to the new node.

Below are the implementation of the above approach:

C++
// Define the structure for a node in the doubly linked list
struct Node {
    int data;   // Data stored in the node
    Node* next; // Pointer to the next node
    Node* prev; // Pointer to the previous node
};

// Function to insert a node at the beginning of the list
void insertBeginning(Node*& head, int value) {
    // Create a new node
    Node* newNode = new Node;

    // Assign the value to the new node
    newNode->data = value;

    // Since it's the first node, the previous pointer is nullptr
    newNode->prev = nullptr;

    // If the list is empty, make the new node the head
    if (head == nullptr) {
        // Since it's the only node, the next pointer is nullptr
        newNode->next = nullptr;

        // Update the head pointer to point to the new node
        head = newNode;
    } else {
        // Point the new node's next pointer to the current head
        newNode->next = head;

        // Update the previous pointer of the current head to point to the new node
        head->prev = newNode;

        // Update the head pointer to point to the new node
        head = newNode;
    }
}

Insertion at the End of Doubly Linked List

Insertion_end_Doubly-Linked-List

Insertion at the End in Doubly Linked List

To insert a new node at the end of the doubly linked list, we can use the following steps:

  • Allocate memory for a new node and assign the provided value to its data field.
  • Initialize the next pointer of the new node to nullptr.
  • If the list is empty:
    • Set the previous pointer of the new node to nullptr.
    • Update the head pointer to point to the new node.
  • If the list is not empty:
    • Traverse the list starting from the head to reach the last node.
    • Adjust pointers to insert the new node at the end:
      • Set the next pointer of the last node to point to the new node.
      • Set the previous pointer of the new node to point to the last node.’

Below are the implementation of the above approach:

C++
#include <iostream>

// Define the structure for a node in the doubly linked list
struct Node {
    int data;      // Data stored in the node
    Node* next;   // Pointer to the next node
    Node* prev;   // Pointer to the previous node
};

// Function to insert a node at the end of the list
void insertEnd(Node*& head, int value) {
    // Create a new node
    Node* newNode = new Node;

    // Assign the value to the new node
    newNode->data = value;

    // Initialize the next pointer to nullptr
    newNode->next = nullptr;

    // Check if the list is empty
    if (head == nullptr) {
        // If the list is empty, make the new node the head
        newNode->prev = nullptr;

        // Update the head pointer to point to the new node
        head = newNode;
    } else {
        // Start from the head of the list
        Node* current = head;

        // Traverse to the end of the list
        while (current->next != nullptr) {
            current = current->next;
        }

        // Adjust pointers to insert the new node at the end
        // Set the next pointer of the last node to point to
        // the new node
        current->next = newNode;

        // Set the previous pointer of the new node to point
        // to the last node
        newNode->prev = current;
    }
}

int main() {
    // Test the insertEnd function
    Node* head = nullptr;
    insertEnd(head, 1);
    insertEnd(head, 2);
    insertEnd(head, 3);

    // Print the list
    Node* current = head;
    while (current != nullptr) {
        std::cout << current->data << " ";
        current = current->next;
    }

    // Delete dynamically allocated memory
    while (head != nullptr) {
        Node* temp = head;
        head = head->next;
        delete temp;
    }

    return 0;
}
Java
// Define the structure for a node in the doubly linked list
class Node {
    int data; // Data stored in the node
    Node next; // Pointer to the next node
    Node prev; // Pointer to the previous node
    
    // Constructor to initialize a node with data
    Node(int data) {
        this.data = data;
        this.next = null;
        this.prev = null;
    }
}

// Function to insert a node at the end of the list
class DoublyLinkedList {
    // Method to insert a node at the end of the list
    static Node insertEnd(Node head, int value) {
        // Create a new node
        Node newNode = new Node(value);

        // Check if the list is empty
        if (head == null) {
            // If the list is empty, make the new node the head
            head = newNode;
        } else {
            // Start from the head of the list
            Node current = head;

            // Traverse to the end of the list
            while (current.next != null) {
                current = current.next;
            }

            // Adjust pointers to insert the new node at the end
            // Set the next pointer of the last node to point to the new node
            current.next = newNode;

            // Set the previous pointer of the new node to point to the last node
            newNode.prev = current;
        }

        return head;
    }
}

// Test the insertEnd function
public class Main {
    public static void main(String[] args) {
        // Initialize an empty list
        Node head = null;

        // Insert nodes at the end of the list
        head = DoublyLinkedList.insertEnd(head, 1);
        head = DoublyLinkedList.insertEnd(head, 2);
        head = DoublyLinkedList.insertEnd(head, 3);

        // Print the list
        Node current = head;
        while (current != null) {
            System.out.println(current.data);
            current = current.next;
        }
    }
}
JavaScript
// Define the structure for a node in the doubly linked list
class Node {
    constructor(data) {
        this.data = data; // Data stored in the node
        this.next = null; // Pointer to the next node
        this.prev = null; // Pointer to the previous node
    }
}

// Function to insert a node at the end of the list
function insertEnd(head, value) {
    // Create a new node
    const newNode = new Node(value);

    // Check if the list is empty
    if (head === null) {
        // If the list is empty, make the new node the head
        head = newNode;
    } else {
        // Start from the head of the list
        let current = head;

        // Traverse to the end of the list
        while (current.next !== null) {
            current = current.next;
        }

        // Adjust pointers to insert the new node at the end
        // Set the next pointer of the last node to point to the new node
        current.next = newNode;

        // Set the previous pointer of the new node to point to the last node
        newNode.prev = current;
    }

    return head;
}

// Test the insertEnd function
let head = null;
head = insertEnd(head, 1);
head = insertEnd(head, 2);
head = insertEnd(head, 3);

// Print the list
let current = head;
while (current !== null) {
    console.log(current.data);
    current = current.next;
}

Insertion at a Specific Position of Doubly Linked List

Insertion_at_specificPosition_Doubly-Linked-List

To insert a node at a specific Position in doubly linked list, we can use the following steps:

  • Traverse the list to find the node at the desired position.
  • Create a new node with the data you want to insert.
  • Adjust the pointers of the new node, the previous node, and the next node to include the new node in the list.
  • Update the pointers of the neighboring nodes to maintain the doubly linked list structure.

Below is the implementation of the above approach:

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

// Define the structure of a node in the doubly linked list
struct Node {
    int data; // Data stored in the node
    Node* prev; // Pointer to the previous node in the list
    Node* next; // Pointer to the next node in the list
};

// Function to insert a node at a specific position in the
// doubly linked list
void insertAtPosition(Node** head, int position, int data) {
    // Create a new node and allocate memory
    Node* newNode = new Node();

    // Set the data of the new node
    newNode->data = data;

    // Insert at the beginning of the list
    if (position == 0) {
        // New node points to the current head
        newNode->next = *head;

        // Previous of new node is null as it's the new head
        newNode->prev = nullptr;

        if (*head != nullptr) {
            // If list is not empty, set the previous of old
            // head to new node
            (*head)->prev = newNode;
        }

        // Update the head to point to the new node
        *head = newNode;
    } else {
        // Pointer to traverse the list
        Node* current = *head;

        // Counter to track the position
        int count = 0;

        // Traverse to the node at position - 1
        while (current != nullptr && count < position - 1) {
            current = current->next; // Move to the next node
            count++; // Increment position counter
        }

        // If reached end of list and position not found
        if (current == nullptr) {
            // Inform user about out of range position
            cout << "Position out of range" << endl;
            return; // Exit function
        }

        // Insert the new node between current and
        // current->next
        newNode->next = current->next; // New node's next is set to
                                       // current node's next
        newNode->prev = current; // New node's previous is
                                 // set to current node

        if (current->next != nullptr) {
            // If there's a node after current, set its
            // previous to new node
            current->next->prev = newNode;
        }

        // Set current node's next to the new node
        current->next = newNode;
    }
}

Deletion at the Beginning of doubly linked list

Deletion_beginning_DLL

Deletion at the Beginning in Doubly Linked List

To delete a node at the beginning in doubly linked list, we can use the following steps:

  • Check If the list is empty, there is nothing to delete. Return.
  • Check if the node to be deleted is the head node, update the head pointer to point to the next node.
  • If the node to be deleted is not the head node, update the previous pointer of the next node to point to the previous node of the node to be deleted.
  • If the node to be deleted is not the tail node, update the next pointer of the previous node to point to the next node of the node to be deleted.
  • Free the memory allocated to the node to be deleted.

Below is the implementation of the above approach:

C++
// Structure to represent a node in a doubly linked list
struct Node {
    int data; // Data stored in the node
    Node* next; // Pointer to the next node in the list
    Node* prev; // Pointer to the previous node in the list
};

// Function to delete the node at the beginning of a doubly
// linked list
void deleteAtBeginning(Node** head) {
    // Check if the list is empty
    if (*head == nullptr) {
        return;
    }

    // Check if the node to be deleted is the head node
    if (*head == (*head)->next) {
        // If the node to be deleted is the head node,
        // update the head pointer to point to the next node
        *head = (*head)->next;

        // If the list has only one node, set the head
        // pointer to NULL
        if (*head == nullptr) {
            return;
        }

        // Update the previous pointer of the new head node
        // to point to NULL
        (*head)->prev = nullptr;
        
        // Delete the old head node
        delete *head;
        return;
    }

    // If the node to be deleted is not the head node,
    // update the previous pointer of the next node to point
    // to the previous node of the node to be deleted
    Node* temp = *head;
    *head = (*head)->next;
    (*head)->prev = nullptr;

    // Delete the node to be deleted
    delete temp;
}

Deletion at the End on doubly linked list:

Deletion_end_DLL

Deletion at a End in Doubly Linked List

To delete a node at the end in doubly linked list, we can use the following steps:

  • Check if the doubly linked list is empty. If it is empty, then there is nothing to delete.
  • If the list is not empty, then move to the last node of the doubly linked list.
  • Update the second-to-last node’s next pointer to NULL, making it the new last node.
  • Free the memory allocated for the node that was deleted.

Below is the implementation of the above approach:

C++
// Structure to represent a node in a doubly linked list
struct Node {
    int data;        // Data stored in the node
    Node* next;     // Pointer to the next node in the list
    Node* prev;     // Pointer to the previous node in the list
};

void deleteAtEnd(Node*& head) {
    // Check if the list is empty
    if (head == nullptr) {
        return;
    }

    // Find the last node
    Node* curr = head;
    while (curr->next != nullptr) {
        curr = curr->next;
    }

    // Update the previous node's next pointer
    Node* prev = nullptr;
    while (prev->next != curr) {
        prev = prev->next;
    }
    prev->next = nullptr;

    // Delete the last node
    delete curr;
}

Deletion at a Specific Position in doubly linked list

Deletion_specificNode_DLL

Deletion at a Specific Position in Doubly Linked List

To delete a node at a specific position in doubly linked list, we can use the following steps:

  • Traverse to the node at the specified position in the doubly linked list.
  • Adjust the pointers to skip the node to be deleted.
  • Update the next pointer of the node before the deleted node to point to the node after the deleted node.
  • Update the previous pointer of the node after the deleted node to point to the node before the deleted node.
  • Free the memory allocated for the deleted node.

Below is the implementation of the above approach:

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

struct Node {
    int data; // Data stored in the node
    Node* next; // Pointer to the next node in the list
    Node* prev; // Pointer to the previous node in the list
};

// Function to traverse the doubly linked list in forward
// direction
void forwardTraversal(Node* head)
{

    // Start traversal from the head of the list
    Node* current = head;

    // Continue until current node is not null (end of list)
    while (current != nullptr) {

        // Output data of the current node
        cout << current->data << " ";

        // Move to the next node
        current = current->next;
    }

    // Print newline after traversal
    cout << endl;
}

// Function to traverse the doubly linked list in backward
// direction
void backwardTraversal(Node* tail)
{

    // Start traversal from the tail of the list
    Node* current = tail;

    // Continue until current node is not null (end of list)
    while (current != nullptr) {

        // Output data of the current node
        cout << current->data << " ";

        // Move to the previous node
        current = current->prev;
    }

    // Print newline after traversal
    cout << endl;
}
Java
class Node {
    int data; // Data stored in the node
    Node prev; // Reference to the previous node in the doubly linked list
    Node next; // Reference to the next node in the doubly linked list
}

void deleteNodeAtPosition(Node head, int position) {
    // If the list is empty, there is nothing to delete
    if (head == null) {
        return;
    }

    Node current = head;

    // Traverse to the node at the specified position
    for (int i = 1; current != null && i < position; ++i) {
        current = current.next;
    }

    // If the specified position is beyond the end of the list, do nothing
    if (current == null) {
        return;
    }

    // Adjust references to skip the node to be deleted
    if (current.prev != null) {
        // Update the next reference of the previous node
        current.prev.next = current.next;
    }
    if (current.next != null) {
        // Update the prev reference of the next node
        current.next.prev = current.prev;
    }

    // Update head if the node to be deleted is the head
    if (head == current) {
        // Update the head reference if the first node is deleted
        head = current.next;
    }

    // Java's garbage collector will automatically deallocate memory for the deleted node
}
Python3
class Node:
    def __init__(self, data=None):
        self.data = data  # Data stored in the node
        self.prev = None  # Reference to the previous node in the doubly linked list
        self.next = None  # Reference to the next node in the doubly linked list

def deleteNodeAtPosition(head, position):
    # If the list is empty, there is nothing to delete
    if head is None:
        return

    current = head

    # Traverse to the node at the specified position
    for i in range(1, position):
        if current is None:
            return
        current = current.next

    # If the specified position is beyond the end of the list, do nothing
    if current is None:
        return

    # Adjust references to skip the node to be deleted
    if current.prev is not None:
        # Update the next reference of the previous node
        current.prev.next = current.next
    if current.next is not None:
        # Update the prev reference of the next node
        current.next.prev = current.prev

    # Update head if the node to be deleted is the head
    if head == current:
        # Update the head reference if the first node is deleted
        head = current.next

    # Python's garbage collector will automatically deallocate memory for the deleted node
JavaScript
class Node {
    constructor(data) {
        this.data = data; // Data stored in the node
        this.next = null; // Pointer to the next node in the list
        this.prev = null; // Pointer to the previous node in the list
    }
}

// Function to traverse the doubly linked list in forward direction
function forwardTraversal(head) {
    let current = head; // Start traversal from the head of the list

    // Continue until current node is not null (end of list)
    while (current !== null) {
        // Output data of the current node
        console.log(current.data + " ");

        // Move to the next node
        current = current.next;
    }

    // Print newline after traversal
    console.log();
}

// Function to traverse the doubly linked list in backward direction
function backwardTraversal(tail) {
    let current = tail; // Start traversal from the tail of the list

    // Continue until current node is not null (end of list)
    while (current !== null) {
        // Output data of the current node
        console.log(current.data + " ");

        // Move to the previous node
        current = current.prev;
    }

    // Print newline after traversal
    console.log();
}

// Example usage
let head = new Node(1);
let second = new Node(2);
let third = new Node(3);

// Connect nodes in a doubly linked list
head.next = second;
second.prev = head;
second.next = third;
third.prev = second;

console.log("Forward Traversal:");
forwardTraversal(head);

console.log("Backward Traversal:");
backwardTraversal(third); // Start from the tail

Advantages of Doubly Linked List

  • Efficient traversal in both directions: Doubly linked lists allow for efficient traversal of the list in both directions, making it suitable for applications where frequent insertions and deletions are required.
  • Easy insertion and deletion of nodes: The presence of pointers to both the previous and next nodes makes it easy to insert or delete nodes from the list, without having to traverse the entire list.
  • Can be used to implement a stack or queue: Doubly linked lists can be used to implement both stacks and queues, which are common data structures used in programming.

Disadvantages of Doubly Linked List

  • More complex than singly linked lists: Doubly linked lists are more complex than singly linked lists, as they require additional pointers for each node.
  • More memory overhead: Doubly linked lists require more memory overhead than singly linked lists, as each node stores two pointers instead of one.

Applications of doubly linked lists:

  • Implementation of undo and redo functionality in text editors.
  • Cache implementation where quick insertion and deletion of elements are required.
  • Browser history management to navigate back and forth between visited pages.
  • Music player applications to manage playlists and navigate through songs efficiently.
  • Implementing data structures like Deque (double-ended queue) for efficient insertion and deletion at both ends.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads