Update appNew update is available. Click here to update.

Doubly Linked List Operations in Data Structure

Ayushi Goyal
Last Updated: Feb 5, 2023
MEDIUM

Introduction

A doubly-linked list is a data structure that consists of sequentially linked records which are called nodes. A node contains two fields, called links, that refer to the previous and the next node in the sequence of nodes. The Questions related to doubly linked lists are frequently asked in leading product-based companies including Amazon, Facebook, Google.

Introduction

This article sheds light on the doubly linked lists and the various operations performed on them with code in Java.

Doubly Linked List Representation

A node in a doubly-linked list consists of three parts, the data, a pointer to the next node of the sequence, and a pointer to the previous sequence node.

As in a singly linked list, a doubly-linked list also has a head pointer that points to the first node of the linked list.

A doubly linked list node in Java is represented as follows:

public class Implementation
{
   Node head; // head of the Linked List
   class Node
   {
       int data;
       Node next;  // Pointer to the next node
       Node prev;  // Pointer to previous node
       
       // Constructor for creating a new node
       Node(int value)
       {
           data = value;
           next = prev = null;
       }
   }
}
A doubly linked list consists of a collection of nodes containing an extra pointer, typically called a previous pointer, together with the next pointer and data which are there in the Singly Linked List. A doubly linked list containing three nodes having numbers from 10 to 30 in their data part is shown in the following image.


The previous pointer of the first node and the next pointer of the last node is set to Null.  The previous pointer set to null indicates that this is the first node of the doubly linked list and the next pointer set to null indicates that this is the last node of the doubly linked list.

Basic Operations on Doubly Linked Lists

Following are the basic operations supported by Doubly Linked Lists:

  1. Insertion: This operation is used for adding new elements to the list. A new element can be added at the front, at the end of a linked list, or after a given node. The various insertion techniques are discussed below.
     
  2. Deletion: This operation is used to remove elements from the list. The node to be deleted may be the first node, last node, or any node in between the first and last node.
     
  3. Traversal: This operation is used to access each element of the list. The Linked List is traversed when printing the contents of the linked list.

Insertion in Doubly Linked Lists

A Node in a doubly-linked list has a pointer to both the previous and the next node of the linked list. Insertion of a new node in an existing doubly linked list can be done in the following places:

  1. Insertion at the Beginning
  2. Insertion at the End
  3. Insertion after a given Node
     

Insertion at the Beginning

The head pointer points to the first node of the doubly linked list, and the previous pointer of the first node points to Null. To insert a node at the beginning of the Linked List, the head pointer should point to the new first node, and the next pointer of the new first node must point to the previous first node.

The code for insertion of a new node at the beginning of a doubly linked list in Java is given below:

// Function for insertion of a new node at the beginning of
// a doubly linked list
public void insertAtBeginning(int data)
{
   // Making a new node with the given data. Note that the
   // previous and next pointer of this node are null
   Node new_node = new Node(data);
   
   // The next pointer of the new node should point to head of DLL i.e. the original first node
   new_node.next = head;
   
   // The previous pointer of new node should point to Null
   new_node.prev = null;
   
   // Change the previous of the node where the head was initially pointing that 
   // is the original first node
   if(head != null)
   {
       head.prev = new_node;
   }
   
   // Head pointer should point to the new node
   head = new_node;
}

Insertion at the End of DLL

The next pointer of the last node of the DLL points to Null. To insert a new node at the last position of the DLL, three important points need to be taken into consideration:

  1. The next pointer of the new node should point to the Null
  2. The previous pointer of the new node should point to the old last node.
  3. The next pointer of the old last node should point to the new last node.
     

Also, there may be a case where the DLL is initially empty. In that case, the newly created node will become both the first and the last node of the doubly linked list.

The code for the insertion of a new node as the last node in Java is given below:

// To insert a node at the end of a Doubly Linked List
public void insertAtLast(int data)
{
   // Creating a new node with the given data
   Node newNode = new Node(data);
   
   // A temporary pointer that will be used for traversing DLL
   Node temp = head;
   
   // Making the next of newNode as Null
   newNode.next = null;
   
   // If DLL is empty then this node will be both the first as
   // well as the last node
   if(head == null)
   {
       newNode.prev = null;
       head = newNode;
       return;
   }
   
   // If DLL is not empty, then traverse till the end of DLL. Make
   // the next pointer of the original last node point to the new
   // last node and the previous of the last node to the original 
   // last node
   
   while(temp.next != null)
   {
       temp = temp.next;
   }  // Now temp points to the original last node
   
   // Illustarted by Blue color in the diagram
   temp.next = newNode;
   // Illstrated by orange color in the diagram
   newNode.prev = temp;
}

Insertion after a given Node

There may be cases wherein a record or data is to be inserted after a given record or data. If the data is stored in a Linked List, the insertion after a given node operation in Linked List is used for such cases.

For inserting a new node after a given node, the following points need to be under consideration:

  1. The records next to the previous node should now be linked to the new node to be inserted.
  2. The previous node’s next pointer should be linked to the new node, and the new node’s previous pointer should be linked to the previous node.
     

The code for insertion of a new node after a given previous node in Java is given below.

public void insertAfter(Node prevNode, int data)
{
   // if the previous node is null
   if(prevNode == null)
   {
       System.out.println("The given previous node cannot be null");
       return;
   }
   
   // Create a new node with the given data
   Node newNode = new Node(data);
   
   // The next pointer of this node should point to
   // the next of prevNode
   newNode.next = prevNode.next;
   
   // The next pointer of prevNode should point to the
   // newNode
   prevNode.next = newNode;
   
   // The previous pointer of newNode should point to the
   // prevNode
   newNode.prev = prevNode;
   
   // Change previous of newNode's next node 
   if (newNode.next != null)
       newNode.next.prev = newNode;
}

Printing a Doubly Linked Lists

The Linked Lists is traversed using a temporary pointer that initially points to the head of the linked list. The temporary pointer is incremented, and the contents of the Doubly Linked List are printed.

Following is the code to print a doubly-linked list in Java

/* A utility function to print the contents of 
a doubly linked list. The function takes the head
pointer of the linked list*/
public void printLinkedList(Node head)
{
   if(head == null)
   {
       System.out.println("The List is empty");
       return;
   }
    // A temporary node that will be used for traversal
   Node temp = head;
   
   System.out.println("Traversal of Linked List");
   
   // Traverse the DLL by incrementing the pointer
   while(temp != null)
   {
       System.out.println(temp.data + " --> ");
       temp = temp.next;
   }
   
}

Deletion in Doubly Linked Lists

There are three cases for deletion of a node in a doubly-linked list:

  • If the node to be deleted is the head node - If the node to be deleted is the head node, then the immediate next node will be the new head node. The head pointer will point to the next node.
     
  • If the node to be deleted is the last node - The second last node will point to Null. All the other nodes will be at their respective positions in the Linked List.
     
  • If the node to be deleted is in between the first and last node - Traverse the linked list until the node is deleted, change the next and previous pointers of the Linked List.
     

The Java program for the deletion of a node in a doubly-linked list is given below:

/* A utility function to delete a node of 
a doubly linked list. The function takes the pointer 
of the node to be deleted*/
void deleteNode(Node ptr)
{
   // Base case where the List is empty
   if(head == null || ptr == null)
   {
       System.out.println("The List is empty");
       return;
   }
   
   // When the node to be deleted is the 
   // head node
   if(ptr == head)
   {
       // The head pointer will now point to the
       // next node 
       head = ptr.next;
      // Since the head node is to be deleted, then the previous of
      // the new head node has to be null
      if(head != null)
                head.prev = null;
     
   }
   
   // If node to be deleted is not the last node
   if(ptr.next != null)
   {
       ptr.next.prev = ptr.prev;
   }
   
   // If node to be deleted is not the first node
   if(ptr.prev != null)
   {
       ptr.prev.next = ptr.next;
   }
}


So now you have a clear understanding of the Doubly Linked list and the various operations that can be performed on it. Below is the complete working program to test the above functions.

Complete Working Program

public class DoubleLinkedList
{
   Node head;
   class Node
   {
       int data;
       Node next, prev;
       public Node(int value){
           data = value;
           next = prev = null;
       }
   }
// Function for insertion of a new node at the beginning of
// a doubly linked list
public void insertAtBeginning(int data)
{
   Node new_node = new Node(data);
   new_node.next = head;
   new_node.prev = null;
   if(head != null){
       head.prev = new_node;
   }
   head = new_node;
}
// To insert a node at the end of a Doubly Linked List
public void insertAtLast(int data)
{
   Node newNode = new Node(data);
   Node temp = head;
   newNode.next = null;
   if(head == null){
       newNode.prev = null;
       head = newNode;
       return;
   }
   while(temp.next != null){
       temp = temp.next;
   } 
   temp.next = newNode;
   newNode.prev = temp;
}
// Function to insert a node after a given node
public void insertAfter(Node prevNode, int data)
{
   if(prevNode == null){
       System.out.println("The given previous node cannot be null");
       return;
   }
   Node newNode = new Node(data);
   newNode.next = prevNode.next;
   prevNode.next = newNode;
   newNode.prev = prevNode;
   if (newNode.next != null)
       newNode.next.prev = newNode;
}
void deleteNode(Node ptr)
{
   if(head == null || ptr == null){
       System.out.println("The List is empty");
       return;
   }
   if(ptr == head){
       head = ptr.next;
   }
   
   if(ptr.next != null){
       ptr.next.prev = ptr.prev;
   }
   
   if(ptr.prev != null){
       ptr.prev.next = ptr.next;
   }
}
public void printLinkedList(Node head)
{
   if(head == null){
       System.out.println("The List is empty");
       return;
   }
   Node temp = head;
   System.out.println("Traversal of Linked List");
   
   while(temp != null){
       if(temp.next == null){
           System.out.println(temp.data);
           return;
       }
       else{
       System.out.print(temp.data + " -> ");
       temp = temp.next;
       }
   }
   
}
public static void main(String[]args)
{
   DoubleLinkedList dll = new DoubleLinkedList();
   dll.insertAtBeginning(10); // 10 -> Null
   dll.insertAtBeginning(0); // 0 -> 10 -> Null
   dll.insertAtLast(20); // 0 -> 10 -> 20 -> Null
   dll.insertAfter(dll.head.next.next, 30); //  0 -> 10 -> 20 -> 30 -> Null
   dll.insertAtLast(60); // 0 -> 10  -> 20 -> 30 -> 60 -> Null
   dll.printLinkedList(dll.head);
   // Node to be deleted is 20
   dll.deleteNode(dll.head.next.next);
   System.out.println("After deletion operation");
   dll.printLinkedList(dll.head);
}
}


The output of the above program is:

output

Advantages of Doubly Linked Lists

Following are the main advantages of Doubly Linked Lists:-

  1. A DLL can be traversed in both forward and reverse directions
  2. A new node can be inserted before a given node quite easily by just changing the pointers.
  3. The complete Linked List need not be traversed for deletion operation as in Singly Linked List.

Disadvantages of Doubly Linked Lists

Following are the main disadvantages of Doubly Linked Lists:-

  1. Additional memory space is required to store the previous pointer and the next pointer and the data to be stored.
  2. All the manipulation operations require both the previous and next pointers to be manipulated, imposing operational overhead.
    For more information, you may refer to the blog.

Frequently Asked Questions

What is a double-ended linked list?

Unlike a doubly linked list which has two pointers, one pointing to the next and the other pointing to the previous node, a doubly ended linked list each node has just one pointer which points to the next node The difference is that instead of just one “head” node, it contains two pointers of this kind (“first” and “last”), so someone is able to insert elements to list from both ends of it.

What is a double-linked list in C?

A double-linked list is a complex data structure wherein data is stored in nodes. Each node has a pointer to the previous as well as the next node of the Linked list.

What is the difference between single and doubly linked lists?

A singly linked list has a pointer pointing to the next node in the sequence. There is no concept of a previous pointer, and a node does not know about the previous node. While in a doubly-linked list, each node has two pointers pointing to the previous as well as the current node, respectively.

What is the difference between array and linked list?

An array is a sequential data structure that stores the elements at contiguous memory locations. A linked list, on the other hand, stores elements at different memory locations. Each node is linked to the next node of the sequence using pointers. There is a head pointer that points to the first node of the linked list.

Conclusion

This blog clearly explained the Doubly Linked Lists, advantages and disadvantages of linked list, and various manipulation techniques were discussed and implemented in Java Programming Language.
 

It is an important topic, and questions related to DLL are frequently asked in almost all the major companies. It would be best if you practiced questions related to the topic to better understand the concepts studied. While this is one of the most important topics, there are other important topics as well.

Questions related to various topics are given in a structured manner in Codestudio. There are Guided Paths and Blogs as well !!

Keep Learning and Keep Exploring!!

Was this article helpful ?
0 upvotes