
- One drawback of a singly linked list is that it can only be traversed singly. Many apps need you to browse through a list’s parts back and forth.
- Making a double-linked list is a helpful improvement over a singly linked list.
- Unlike singly linked lists, which have pointers pointing in only one direction, doubly linked lists have pointers pointing to both the previous and next nodes.
- A doubly linked list’s primary benefit is that it allows for both direction traversal and searching of the list.
- Every node in this linked list has three fields.
- One is used to hold data, and the others are self-referential pointers that point to the nodes in the list that come before and after it.
Doubly Linked List Operations:
- Insertion operation
- Deletion operation
Table of Contents
Insertion operation
Three cases exist for an element to be added to the list.
- Insertion at the beginning of DLL
- Insertion at the end of the DLL
- Insertion at a specific location in the DLL
Case 1: Insertion at the beginning of DLL

- Construct a new node, new_node, using the provided data, and assign null to its previous pointer, new_node->prev = NULL.
- New_node->next = head; this sets the next pointer of new_node to the current head.
- Head->prev = new_node is the updated reference to the previous head if the linked list is not empty.
- As the head of the revised linked list, return new_node.
Implementation of the Program in 4 languages using the above approach
class Node: def __init__(self, data): self.data = data # Store the data in the node self.prev = None # Pointer to the previous node self.next = None # Pointer to the next node class DoublyLinkedList: def __init__(self): self.head = None # Initialize the head of the list def push(self, new_data): """Inserts a new node with 'new_data' at the beginning of the doubly linked list.""" # 1. Allocate memory for the new node new_node = Node(new_data) # 2. If the list is empty, make the new node both head and tail if self.head is None: self.head = new_node return # 3. Set the previous pointer of the current head to the new node self.head.prev = new_node # 4. Make the next of the new node as the head new_node.next = self.head # 5. Move the head to point to the new node self.head = new_node def printList(self, node): """Prints the data of all nodes in the doubly linked list.""" while node is not None: print(node.data, end=" ") last = node node = node.next # Example usage: dll = DoublyLinkedList() dll.push(2) dll.push(4) dll.push(8) dll.push(10) print("Created DLL is: ") dll.printList(dll.head) # Output: 10 8 4 2
#include <iostream> using namespace std; // Node structure for a doubly linked list struct Node { int data; Node* prev; Node* next; }; class DoublyLinkedList { public: Node* head; // Pointer to the head of the list DoublyLinkedList() : head(nullptr) {} // Constructor // Function to insert a new node at the beginning void push(int new_data) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. Make next of new node as head and previous as NULL new_node->next = head; new_node->prev = nullptr; // 4. Change prev of head node to new node if (head != nullptr) { head->prev = new_node; } // 5. Move the head to point to the new node head = new_node; } // Function to print the doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " "; node = node->next; } cout << endl; } }; // Example usage int main() { DoublyLinkedList dll; dll.push(2); dll.push(4); dll.push(8); dll.push(10); cout << "Created DLL is: "; dll.printList(dll.head); // Output: 10 8 4 2 return 0; }
class Node { int data; Node prev; Node next; // Constructor to create a new node Node(int d) { data = d; prev = null; next = null; } } class DoublyLinkedList { Node head; // Head of the list // Function to insert a new node at the beginning of the Doubly Linked List public void push(int new_data) { // 1. Allocate the Node & put in the data Node new_Node = new Node(new_data); // 2. Make next of new node as head and previous as NULL new_Node.next = head; new_Node.prev = null; // 3. Change prev of head node to new node if (head != null) { head.prev = new_Node; } // 4. Move the head to point to the new node head = new_Node; } // Function to print nodes in a given doubly linked list public void printList(Node node) { while (node != null) { System.out.print(node.data + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.push(2); dll.push(4); dll.push(8); dll.push(10); System.out.print("Created DLL is: "); dll.printList(dll.head); // Output: 10 8 4 2 } }
#include <stdio.h> #include <stdlib.h> // Structure of a node in the Doubly Linked List struct Node { int data; struct Node* prev; struct Node* next; }; // Function to insert a new node at the beginning of the Doubly Linked List void push(struct Node** head_ref, int new_data) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. Make next of new node as head and previous as NULL new_node->next = (*head_ref); new_node->prev = NULL; // 4. Change prev of head node to new node if ((*head_ref) != NULL) { (*head_ref)->prev = new_node; } // 5. Move the head to point to the new node (*head_ref) = new_node; } // Function to print nodes in a given doubly linked list void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { struct Node* head = NULL; // Start with an empty list push(&head, 2); push(&head, 4); push(&head, 8); push(&head, 10); printf("Created DLL is: "); printList(head); // Output: 10 8 4 2 return 0; }
Output:
Created DLL is:
10 8 4 2
Case 2: Insertion at the end of the DLL

- The following procedures can be used to add a new node to the end of the doubly linked list:
- A new node should have memory allocated to it and its data field should be given the given value.
- Set the new node’s next pointer’s initial value to nullptr.
- If the list is empty:
- Assign nullptr to the new node’s prior pointer.
- To point to the new node, update the head pointer.
- Should the list not be empty:
- To get the last node, go through the list beginning at the head.
- Assign the new node’s pointer to the previous node’s next pointer.
- Make sure the new node’s previous pointer points to the final node.
Implementation of the Program in 4 languages using the above approach
class Node: def __init__(self, data): self.data = data # Store the data in the node self.prev = None # Pointer to the previous node self.next = None # Pointer to the next node class DoublyLinkedList: def __init__(self): self.head = None # Initialize the head of the list def append(self, new_data): """Inserts a new node with 'new_data' at the end of the doubly linked list.""" # 1. Allocate memory for the new node new_node = Node(new_data) # 2. If the list is empty, make the new node the head if self.head is None: self.head = new_node return # 3. Traverse to the last node last = self.head while last.next: last = last.next # 4. Change the next of the last node last.next = new_node # 5. Make the last node the previous of the new node new_node.prev = last def printList(self, node): """Prints the data of all nodes in the doubly linked list.""" while node: print(node.data, end=" ") last = node node = node.next # Example usage: dll = DoublyLinkedList() dll.append(2) dll.append(4) dll.append(8) dll.append(10) print("Created DLL is: ") dll.printList(dll.head) # Output: 2 4 8 10
#include <iostream> using namespace std; // Node structure for a doubly linked list struct Node { int data; Node* prev; Node* next; }; class DoublyLinkedList { public: Node* head; // Pointer to the head of the list DoublyLinkedList() : head(nullptr) {} // Constructor // Function to insert a new node at the end void append(int new_data) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = nullptr; // 4. If the Linked List is empty, then make the new node as head if (head == nullptr) { new_node->prev = nullptr; head = new_node; return; } // 5. Else traverse till the last node Node* last = head; while (last->next != nullptr) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to print the doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " "; node = node->next; } cout << endl; } }; // Example usage int main() { DoublyLinkedList dll; dll.append(2); dll.append(4); dll.append(8); dll.append(10); cout << "Created DLL is: "; dll.printList(dll.head); // Output: 2 4 8 10 return 0; }
class Node { int data; Node prev; Node next; // Constructor to create a new node Node(int d) { data = d; prev = null; next = null; } } class DoublyLinkedList { Node head; // Head of the list // Function to insert a new node at the end of the Doubly Linked List public void append(int new_data) { // 1. Allocate the Node & put in the data Node new_node = new Node(new_data); // 2. This new node is going to be the last node, so make next of it as null new_node.next = null; // 3. If the Linked List is empty, then make the new node as head if (head == null) { new_node.prev = null; head = new_node; return; } // 4. Else traverse till the last node Node last = head; while (last.next != null) last = last.next; // 5. Change the next of the last node last.next = new_node; // 6. Make last node as previous of new node new_node.prev = last; } // Function to print nodes in a given doubly linked list public void printList(Node node) { while (node != null) { System.out.print(node.data + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.append(2); dll.append(4); dll.append(8); dll.append(10); System.out.print("Created DLL is: "); dll.printList(dll.head); // Output: 2 4 8 10 } }
#include <stdio.h> #include <stdlib.h> // Structure of a node in the Doubly Linked List struct Node { int data; struct Node* prev; struct Node* next; }; // Function to insert a new node at the end of the Doubly Linked List void append(struct Node** head_ref, int new_data) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = NULL; // 4. If the Linked List is empty, then make the new node as head if ((*head_ref) == NULL) { new_node->prev = NULL; (*head_ref) = new_node; return; } // 5. Else traverse till the last node struct Node* last = (*head_ref); while (last->next != NULL) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to print nodes in a given doubly linked list void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { struct Node* head = NULL; // Start with an empty list append(&head, 2); append(&head, 4); append(&head, 8); append(&head, 10); printf("Created DLL is: "); printList(head); // Output: 2 4 8 10 return 0; }
Output:
Created DLL is:
2 4 8 10
Case 3: Insertion at a specific location in the DLL

- To add a new node at a certain location,
- Make a new node, put it at the head of the linked list, and return it if position = 1.
- If not, go through the list until you get the node at position-1, say curr.
- Create a new node called new_node with the provided data if the location is valid.
- New_node->next = curr->next and new_node->prior = curr update the next pointer of the new node to the next of the current node and the prev pointer of the new node to the current node.
- Likewise, change curr->next = new_node, the current node’s next pointer, to refer to the new node.
- Update the prev pointer of the new nodes adjacent to the latest node, new_node->next->prev = new_node, if the new node is not the final node.
Implementation of the Program in 4 languages using the above approach
class Node: def __init__(self, data): self.data = data self.prev = None self.next = None class DoublyLinkedList: def __init__(self): self.head = None def insert_at_position(self, new_data, position): """Inserts a new node with 'new_data' at the specified 'position' in the doubly linked list.""" # 1. Create the new node new_node = Node(new_data) # 2. If the list is empty, make the new node the head if self.head is None: self.head = new_node return # 3. If inserting at position 0 (beginning), handle it separately if position == 0: new_node.next = self.head self.head.prev = new_node self.head = new_node return # 4. Traverse to the node before the desired position temp = self.head count = 0 while temp is not None and count < position - 1: temp = temp.next count += 1 # 5. If the position is beyond the list length, insert at the end if temp is None: self.append(new_data) # Use the append method to insert at the end return # 6. Insert the new node at the desired position new_node.next = temp.next new_node.prev = temp if temp.next is not None: temp.next.prev = new_node temp.next = new_node def append(self, new_data): """Inserts a new node at the end of the doubly linked list.""" new_node = Node(new_data) if self.head is None: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node new_node.prev = last def printList(self, node): """Prints the data of all nodes in the doubly linked list.""" while node: print(node.data, end=" ") node = node.next # Example usage: dll = DoublyLinkedList() dll.append(1) dll.append(3) dll.append(4) dll.insert_at_position(2, 1) # Insert 2 at position 1 dll.printList(dll.head) # Output: 1 2 3 4
#include <iostream> using namespace std; // Node structure for a doubly linked list struct Node { int data; Node* prev; Node* next; }; class DoublyLinkedList { public: Node* head; // Pointer to the head of the list DoublyLinkedList() : head(nullptr) {} // Constructor // Function to insert a new node at the end void append(int new_data) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = nullptr; // 4. If the Linked List is empty, then make the new node as head if (head == nullptr) { new_node->prev = nullptr; head = new_node; return; } // 5. Else traverse till the last node Node* last = head; while (last->next != nullptr) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to insert a new node at a given position void insertAtPosition(int new_data, int position) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. If the linked list is empty, make the new node as head if (head == nullptr) { new_node->prev = nullptr; head = new_node; return; } // 4. If the position is 0, handle it like inserting at the beginning if (position == 0) { new_node->next = head; new_node->prev = nullptr; head->prev = new_node; head = new_node; return; } // 5. Else traverse till the position - 1 node Node* temp = head; for (int i = 0; i < position - 1 && temp != nullptr; i++) { temp = temp->next; } // 6. If the position is more than the number of nodes, insert at the end if (temp == nullptr) { append(new_data); return; } // 7. Adjust the pointers to insert the new node new_node->next = temp->next; new_node->prev = temp; if (temp->next != nullptr) { temp->next->prev = new_node; } temp->next = new_node; } // Function to print the doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " "; node = node->next; } cout << endl; } }; // Example usage int main() { DoublyLinkedList dll; dll.append(1); dll.append(3); dll.append(4); dll.insertAtPosition(2, 1); // Insert 2 at position 1 cout << "Created DLL is: "; dll.printList(dll.head); // Output: 1 2 3 4 return 0; }
class Node { int data; Node prev; Node next; // Constructor to create a new node Node(int d) { data = d; prev = null; next = null; } } class DoublyLinkedList { Node head; // Head of the list // Function to insert a new node at the end of the Doubly Linked List public void append(int new_data) { // 1. Allocate the Node & put in the data Node new_node = new Node(new_data); // 2. This new node is going to be the last node, so make next of it as null new_node.next = null; // 3. If the Linked List is empty, then make the new node as head if (head == null) { new_node.prev = null; head = new_node; return; } // 4. Else traverse till the last node Node last = head; while (last.next != null) last = last.next; // 5. Change the next of the last node last.next = new_node; // 6. Make last node as previous of new node new_node.prev = last; } // Function to insert a new node at a given position public void insertAtPosition(int new_data, int position) { // 1. Allocate the Node & put in the data Node new_node = new Node(new_data); // 2. If the Linked List is empty, then make the new node as head if (head == null) { new_node.prev = null; head = new_node; return; } // 3. If the position is 0, handle it like inserting at the beginning if (position == 0) { new_node.next = head; new_node.prev = null; head.prev = new_node; head = new_node; return; } // 4. Else traverse till the position - 1 node Node temp = head; for (int i = 0; i < position - 1 && temp != null; i++) { temp = temp.next; } // 5. If the position is more than the number of nodes, insert at the end if (temp == null) { append(new_data); return; } // 6. Adjust the pointers to insert the new node new_node.next = temp.next; new_node.prev = temp; if (temp.next != null) { temp.next.prev = new_node; } temp.next = new_node; } // Function to print nodes in a given doubly linked list public void printList(Node node) { while (node != null) { System.out.print(node.data + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.append(1); dll.append(3); dll.append(4); dll.insertAtPosition(2, 1); // Insert 2 at position 1 System.out.print("Created DLL is: "); dll.printList(dll.head); // Output: 1 2 3 4 } }
#include <stdio.h> #include <stdlib.h> // Structure of a node in the Doubly Linked List struct Node { int data; struct Node* prev; struct Node* next; }; // Function to insert a new node at the end of the Doubly Linked List void append(struct Node** head_ref, int new_data) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = NULL; // 4. If the Linked List is empty, then make the new node as head if ((*head_ref) == NULL) { new_node->prev = NULL; (*head_ref) = new_node; return; } // 5. Else traverse till the last node struct Node* last = (*head_ref); while (last->next != NULL) last = last->next; // 6. Change the next of the last node last->next = new_node; // 7. Make last node as previous of new node new_node->prev = last; } // Function to insert a new node at a given position void insertAtPosition(struct Node** head_ref, int new_data, int position) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. If the linked list is empty, make the new node as head if (*head_ref == NULL) { new_node->prev = NULL; *head_ref = new_node; return; } // 4. If the position is 0, handle it like inserting at the beginning if (position == 0) { new_node->next = *head_ref; new_node->prev = NULL; (*head_ref)->prev = new_node; *head_ref = new_node; return; } // 5. Else traverse till the position - 1 node struct Node* temp = *head_ref; for (int i = 0; temp != NULL && i < position - 1; i++) { temp = temp->next; } // 6. If the position is more than the number of nodes, insert at the end if (temp == NULL) { append(head_ref, new_data); return; } // 7. Adjust the pointers to insert the new node new_node->next = temp->next; new_node->prev = temp; if (temp->next != NULL) { temp->next->prev = new_node; } temp->next = new_node; } // Function to print nodes in a given doubly linked list void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { struct Node* head = NULL; // Start with an empty list append(&head, 1); append(&head, 3); append(&head, 4); insertAtPosition(&head, 2, 1); // Insert 2 at position 1 printf("Created DLL is: "); printList(head); // Output: 1 2 3 4 return 0; }
Output:
1 2 3 4
Deletion operation
Three cases exist for an element to be added to the list.
- Deletion at the beginning of DLL
- Deletion at the end of the DLL
- Deletion at a specific location in the DLL
Case 1: Deletion at the beginning of the DLL

- The following actions can be taken to remove the first node in a doubly linked list:
- Verify that the list is empty and that nothing needs to be deleted. Go back.
- The head pointer should be kept in a variable, like temp.
- Head = head->next updates the head of the linked list to the node adjacent to the current head.
- Update head->prev = NULL to reflect the new head’s previous reference to NULL if it is not NULL.
Implementation of the Program in 4 languages using the above approach
class Node: def __init__(self, data): self.data = data self.prev = None self.next = None class DoublyLinkedList: def __init__(self): self.head = None def delete_at_beginning(self): """Deletes the node at the beginning of the doubly linked list.""" # 1. If the list is empty, do nothing if self.head is None: return # 2. If the list has only one node, set head to None if self.head.next is None: self.head = None return # 3. Update the head to the next node self.head = self.head.next # 4. Set the 'prev' pointer of the new head to None self.head.prev = None def printList(self, node): """Prints the data of all nodes in the doubly linked list.""" while node is not None: print(node.data, end=" ") last = node node = node.next # Example usage: dll = DoublyLinkedList() dll.append(2) dll.append(4) dll.append(8) dll.append(10) print("Created DLL is: ") dll.printList(dll.head) # Output: 2 4 8 10 dll.delete_at_beginning() print("\nDLL after deleting the first node: ") dll.printList(dll.head) # Output: 4 8 10
#include <iostream> using namespace std; // Node structure for a doubly linked list struct Node { int data; Node* prev; Node* next; }; class DoublyLinkedList { public: Node* head; // Pointer to the head of the list DoublyLinkedList() : head(nullptr) {} // Constructor // Function to insert a new node at the end void append(int new_data) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = nullptr; // 4. If the Linked List is empty, then make the new node as head if (head == nullptr) { new_node->prev = nullptr; head = new_node; return; } // 5. Else traverse till the last node Node* last = head; while (last->next != nullptr) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to delete a node at the beginning of the Doubly Linked List void deleteAtBeginning() { // 1. If the list is empty, do nothing if (head == nullptr) { return; } // 2. Store the old head Node* temp = head; // 3. If the list has only one node, set head to NULL if (head->next == nullptr) { head = nullptr; } else { // 4. Move the head pointer to the next node head = head->next; // 5. Set the 'prev' pointer of the new head to NULL head->prev = nullptr; } // 6. Free the memory occupied by the deleted node delete temp; } // Function to print nodes in a given doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " "; node = node->next; } cout << endl; } }; // Example usage int main() { DoublyLinkedList dll; dll.append(2); dll.append(4); dll.append(8); dll.append(10); cout << "Created DLL is: "; dll.printList(dll.head); // Output: 2 4 8 10 dll.deleteAtBeginning(); cout << "\nDLL after deleting the first node: "; dll.printList(dll.head); // Output: 4 8 10 return 0; }
class Node { int data; Node prev; Node next; // Constructor to create a new node Node(int d) { data = d; prev = null; next = null; } } class DoublyLinkedList { Node head; // Head of the list // Function to insert a new node at the end of the Doubly Linked List public void append(int new_data) { // 1. Allocate the Node & put in the data Node new_node = new Node(new_data); // 2. This new node is going to be the last node, so make next of it as null new_node.next = null; // 3. If the Linked List is empty, then make the new node as head if (head == null) { new_node.prev = null; head = new_node; return; } // 4. Else traverse till the last node Node last = head; while (last.next != null) last = last.next; // 5. Change the next of the last node last.next = new_node; // 6. Make last node as previous of new node new_node.prev = last; } // Function to delete a node at the beginning of the Doubly Linked List public void deleteAtBeginning() { // 1. If the list is empty, do nothing if (head == null) { return; } // 2. If the list has only one node, set head to null if (head.next == null) { head = null; return; } // 3. Move the head pointer to the next node head = head.next; // 4. Set the 'prev' pointer of the new head to null head.prev = null; } // Function to print nodes in a given doubly linked list public void printList(Node node) { while (node != null) { System.out.print(node.data + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.append(2); dll.append(4); dll.append(8); dll.append(10); System.out.print("Created DLL is: "); dll.printList(dll.head); // Output: 2 4 8 10 dll.deleteAtBeginning(); System.out.print("\nDLL after deleting the first node: "); dll.printList(dll.head); // Output: 4 8 10 } }
#include <stdio.h> #include <stdlib.h> // Structure of a node in the Doubly Linked List struct Node { int data; struct Node* prev; struct Node* next; }; // Function to insert a new node at the end of the Doubly Linked List void append(struct Node** head_ref, int new_data) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = NULL; // 4. If the Linked List is empty, then make the new node as head if ((*head_ref) == NULL) { new_node->prev = NULL; (*head_ref) = new_node; return; } // 5. Else traverse till the last node struct Node* last = (*head_ref); while (last->next != NULL) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to delete a node at the beginning of the Doubly Linked List void deleteAtBeginning(struct Node** head_ref) { // 1. If the list is empty, do nothing if (*head_ref == NULL) { return; } // 2. Store the old head struct Node* temp = *head_ref; // 3. If the list has only one node, set head to NULL if ((*head_ref)->next == NULL) { *head_ref = NULL; } else { // 4. Move the head pointer to the next node *head_ref = (*head_ref)->next; // 5. Set the 'prev' pointer of the new head to NULL (*head_ref)->prev = NULL; } // 6. Free the memory occupied by the deleted node free(temp); } // Function to print nodes in a given doubly linked list void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { struct Node* head = NULL; // Start with an empty list append(&head, 2); append(&head, 4); append(&head, 8); append(&head, 10); printf("Created DLL is: "); printList(head); // Output: 2 4 8 10 deleteAtBeginning(&head); printf("\nDLL after deleting the first node: "); printList(head); // Output: 4 8 10 return 0; }
Output:
Created DLL is: 2 4 8 10
DLL after deleting the first node: 4 8 10
Case 2: Deletion at the end of the DLL

- In a doubly linked list, we may use the following procedures to remove the last node:
- Verify that the doubly linked list has no entries. There is nothing to remove if it is empty.
- Proceed to the last node of the doubly linked list, say curr if the list is not empty.
- curr->prev->next = NULL, update the next pointer of the second–to-last node to NULL.
- Release the memory used for the removed node.
Implementation of the Program in 4 languages using the above approach
class Node: def __init__(self, data): self.data = data self.prev = None self.next = None class DoublyLinkedList: def __init__(self): self.head = None def append(self, new_data): """Inserts a new node with 'new_data' at the end of the doubly linked list.""" new_node = Node(new_data) if self.head is None: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node new_node.prev = last def delete_at_end(self): """Deletes the node at the end of the doubly linked list.""" # 1. If the list is empty, do nothing if self.head is None: return # 2. If the list has only one node, set head to None if self.head.next is None: self.head = None return # 3. Traverse to the last node temp = self.head while temp.next: temp = temp.next # 4. Set the 'next' pointer of the second-to-last node to None temp.prev.next = None # 5. Delete the last node (temp) del temp def printList(self, node): """Prints the data of all nodes in the doubly linked list.""" while node: print(node.data, end=" ") last = node node = node.next # Example usage: dll = DoublyLinkedList() dll.append(2) dll.append(4) dll.append(8) dll.append(10) print("Created DLL is: ") dll.printList(dll.head) # Output: 2 4 8 10 dll.delete_at_end() print("\nDLL after deleting the last node: ") dll.printList(dll.head) # Output: 2 4 8
#include <iostream> using namespace std; // Node structure for a doubly linked list struct Node { int data; Node* prev; Node* next; }; class DoublyLinkedList { public: Node* head; // Pointer to the head of the list DoublyLinkedList() : head(nullptr) {} // Constructor // Function to insert a new node at the end void append(int new_data) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = nullptr; // 4. If the Linked List is empty, then make the new node as head if (head == nullptr) { new_node->prev = nullptr; head = new_node; return; } // 5. Else traverse till the last node Node* last = head; while (last->next != nullptr) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to delete the node at the end of the Doubly Linked List void deleteAtEnd() { // 1. If the list is empty, do nothing if (head == nullptr) { return; } // 2. If the list has only one node, set head to NULL if (head->next == nullptr) { delete head; head = nullptr; return; } // 3. Traverse to the last node Node* temp = head; while (temp->next != nullptr) { temp = temp->next; } // 4. Set the 'next' pointer of the second-to-last node to NULL temp->prev->next = nullptr; // 5. Delete the last node delete temp; } // Function to print nodes in a given doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " "; node = node->next; } cout << endl; } }; // Example usage int main() { DoublyLinkedList dll; dll.append(2); dll.append(4); dll.append(8); dll.append(10); cout << "Created DLL is: "; dll.printList(dll.head); // Output: 2 4 8 10 dll.deleteAtEnd(); cout << "\nDLL after deleting the last node: "; dll.printList(dll.head); // Output: 2 4 8 return 0; }
class Node { int data; Node prev; Node next; // Constructor to create a new node Node(int d) { data = d; prev = null; next = null; } } class DoublyLinkedList { Node head; // Head of the list // Function to insert a new node at the end of the Doubly Linked List public void append(int new_data) { // 1. Allocate the Node & put in the data Node new_node = new Node(new_data); // 2. This new node is going to be the last node, so make next of it as null new_node.next = null; // 3. If the Linked List is empty, then make the new node as head if (head == null) { new_node.prev = null; head = new_node; return; } // 4. Else traverse till the last node Node last = head; while (last.next != null) last = last.next; // 5. Change the next of the last node last.next = new_node; // 6. Make last node as previous of new node new_node.prev = last; } // Function to delete a node at the end of the Doubly Linked List public void deleteAtEnd() { // 1. If the list is empty, do nothing if (head == null) { return; } // 2. If the list has only one node, set head to null if (head.next == null) { head = null; return; } // 3. Traverse to the last node Node temp = head; while (temp.next != null) { temp = temp.next; } // 4. Set the 'next' pointer of the second to last node to null temp.prev.next = null; } // Function to print nodes in a given doubly linked list public void printList(Node node) { while (node != null) { System.out.print(node.data + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.append(2); dll.append(4); dll.append(8); dll.append(10); System.out.print("Created DLL is: "); dll.printList(dll.head); // Output: 2 4 8 10 dll.deleteAtEnd(); System.out.print("\nDLL after deleting the last node: "); dll.printList(dll.head); // Output: 2 4 8 } }
#include <stdio.h> #include <stdlib.h> // Structure of a node in the Doubly Linked List struct Node { int data; struct Node* prev; struct Node* next; }; // Function to insert a new node at the end of the Doubly Linked List void append(struct Node** head_ref, int new_data) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = NULL; // 4. If the Linked List is empty, then make the new node as head if ((*head_ref) == NULL) { new_node->prev = NULL; (*head_ref) = new_node; return; } // 5. Else traverse till the last node struct Node* last = (*head_ref); while (last->next != NULL) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to delete a node at the end of the Doubly Linked List void deleteAtEnd(struct Node** head_ref) { // 1. If the list is empty, do nothing if (*head_ref == NULL) { return; } // 2. If the list has only one node, set head to NULL if ((*head_ref)->next == NULL) { free(*head_ref); *head_ref = NULL; return; } // 3. Traverse to the last node struct Node* temp = *head_ref; while (temp->next != NULL) { temp = temp->next; } // 4. Set the 'next' pointer of the second-to-last node to NULL temp->prev->next = NULL; // 5. Free the memory occupied by the deleted node free(temp); } // Function to print nodes in a given doubly linked list void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { struct Node* head = NULL; // Start with an empty list append(&head, 2); append(&head, 4); append(&head, 8); append(&head, 10); printf("Created DLL is: "); printList(head); // Output: 2 4 8 10 deleteAtEnd(&head); printf("\nDLL after deleting the last node: "); printList(head); // Output: 2 4 8 return 0; }
Output:
Created DLL is:
2 4 8 10
DLL after deleting the last node:
2 4 8
Case 3: Deletion at a specific location of the DLL

- The following procedures can be used to remove a node from a doubly linked list at a certain position:
- Say, curr when you approach the node at the designated location.
- Modify the pointers to bypass the node that has to be destroyed if the location is valid.
- For non-head nodes, the next pointer of the predecessor node should be modified to point to the successor node: curr->prev->next = curr->next.
- Curr->next->prev = curr->prev is the new pointer from the node after curr to the node before curr if curr is not the last node in the linked list.
- Release the memory used by the node that was removed.
Implementation of the Program in 4 languages using the above approach
class Node: def __init__(self, data): self.data = data self.prev = None self.next = None class DoublyLinkedList: def __init__(self): self.head = None def append(self, new_data): """Inserts a new node at the end of the doubly linked list.""" new_node = Node(new_data) if self.head is None: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node new_node.prev = last def delete_at_position(self, position): """Deletes the node at the specified 'position' in the doubly linked list.""" # 1. If the list is empty, do nothing if self.head is None: return # 2. If the position is 0, delete the head node if position == 0: # If only one node, set head to None if self.head.next is None: self.head = None return # Update head to the next node and set its 'prev' to None self.head = self.head.next self.head.prev = None return # 3. Traverse to the node at the given position temp = self.head count = 0 while temp is not None and count < position: temp = temp.next count += 1 # 4. If the position is beyond the list length, do nothing if temp is None: return # 5. If the node to be deleted is not the last node if temp.next is not None: temp.next.prev = temp.prev # 6. If the node to be deleted is not the first node if temp.prev is not None: temp.prev.next = temp.next # 7. Delete the node del temp def printList(self, node): """Prints the data of all nodes in the doubly linked list.""" while node: print(node.data, end=" ") node = node.next # Example usage: dll = DoublyLinkedList() dll.append(2) dll.append(4) dll.append(8) dll.append(10) print("Created DLL is: ") dll.printList(dll.head) # Output: 2 4 8 10 dll.delete_at_position(2) # Delete node at position 2 print("\nDLL after deleting at position 2: ") dll.printList(dll.head) # Output: 2 4 10
#include <iostream> using namespace std; // Node structure for a doubly linked list struct Node { int data; Node* prev; Node* next; }; class DoublyLinkedList { public: Node* head; // Pointer to the head of the list DoublyLinkedList() : head(nullptr) {} // Constructor // Function to insert a new node at the end void append(int new_data) { // 1. Allocate memory for the new node Node* new_node = new Node; // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = nullptr; // 4. If the Linked List is empty, then make the new node as head if (head == nullptr) { new_node->prev = nullptr; head = new_node; return; } // 5. Else traverse till the last node Node* last = head; while (last->next != nullptr) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make the last node as previous of the new node new_node->prev = last; } // Function to delete a node at a given position void deleteAtPosition(int position) { // 1. If the list is empty, do nothing if (head == nullptr) { return; } // 2. If the position is 0, delete the head node if (position == 0) { Node* temp = head; head = head->next; if (head != nullptr) { head->prev = nullptr; } delete temp; return; } // 3. Traverse to the node at the given position Node* temp = head; for (int i = 0; temp != nullptr && i < position; i++) { temp = temp->next; } // 4. If the position is more than the number of nodes, do nothing if (temp == nullptr) { return; } // 5. If the node to be deleted is not the last node if (temp->next != nullptr) { temp->next->prev = temp->prev; } // 6. If the node to be deleted is not the first node if (temp->prev != nullptr) { temp->prev->next = temp->next; } // 7. Delete the node delete temp; } // Function to print nodes in a given doubly linked list void printList(Node* node) { while (node != nullptr) { cout << node->data << " "; node = node->next; } cout << endl; } }; // Example usage int main() { DoublyLinkedList dll; dll.append(2); dll.append(4); dll.append(8); dll.append(10); cout << "Created DLL is: "; dll.printList(dll.head); // Output: 2 4 8 10 dll.deleteAtPosition(2); // Delete node at position 2 cout << "\nDLL after deleting at position 2: "; dll.printList(dll.head); // Output: 2 4 10 return 0; }
class Node { int data; Node prev; Node next; // Constructor to create a new node Node(int d) { data = d; prev = null; next = null; } } class DoublyLinkedList { Node head; // Head of the list // Function to insert a new node at the end of the Doubly Linked List public void append(int new_data) { // 1. Allocate the Node & put in the data Node new_node = new Node(new_data); // 2. This new node is going to be the last node, so make next of it as null new_node.next = null; // 3. If the Linked List is empty, then make the new node as head if (head == null) { new_node.prev = null; head = new_node; return; } // 4. Else traverse till the last node Node last = head; while (last.next != null) last = last.next; // 5. Change the next of the last node last.next = new_node; // 6. Make last node as previous of new node new_node.prev = last; } // Function to delete a node at a given position public void deleteAtPosition(int position) { // 1. If the list is empty, do nothing if (head == null) { return; } // 2. If the position is 0, delete the head node if (position == 0) { head = head.next; if (head != null) { head.prev = null; } return; } // 3. Traverse to the node at the given position Node temp = head; for (int i = 0; temp != null && i < position; i++) { temp = temp.next; } // 4. If the position is more than the number of nodes, do nothing if (temp == null) { return; } // 5. If the node to be deleted is not the last node if (temp.next != null) { temp.next.prev = temp.prev; } // 6. If the node to be deleted is not the first node if (temp.prev != null) { temp.prev.next = temp.next; } } // Function to print nodes in a given doubly linked list public void printList(Node node) { while (node != null) { System.out.print(node.data + " "); node = node.next; } System.out.println(); } public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.append(2); dll.append(4); dll.append(8); dll.append(10); System.out.print("Created DLL is: "); dll.printList(dll.head); // Output: 2 4 8 10 dll.deleteAtPosition(2); // Delete node at position 2 System.out.print("\nDLL after deleting at position 2: "); dll.printList(dll.head); // Output: 2 4 10 } }
#include <stdio.h> #include <stdlib.h> // Structure of a node in the Doubly Linked List struct Node { int data; struct Node* prev; struct Node* next; }; // Function to insert a new node at the end of the Doubly Linked List void append(struct Node** head_ref, int new_data) { // 1. Allocate memory for the new node struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); // 2. Put in the data new_node->data = new_data; // 3. This new node is going to be the last node, so make next of it as NULL new_node->next = NULL; // 4. If the Linked List is empty, then make the new node as head if ((*head_ref) == NULL) { new_node->prev = NULL; (*head_ref) = new_node; return; } // 5. Else traverse till the last node struct Node* last = (*head_ref); while (last->next != NULL) { last = last->next; } // 6. Change the next of the last node last->next = new_node; // 7. Make last node as previous of new node new_node->prev = last; } // Function to delete a node at a given position void deleteAtPosition(struct Node** head_ref, int position) { // 1. If the list is empty, do nothing if (*head_ref == NULL) { return; } // 2. If the position is 0, delete the head node if (position == 0) { struct Node* temp = *head_ref; *head_ref = (*head_ref)->next; if (*head_ref != NULL) { (*head_ref)->prev = NULL; } free(temp); return; } // 3. Traverse to the node at the given position struct Node* temp = *head_ref; for (int i = 0; temp != NULL && i < position; i++) { temp = temp->next; } // 4. If the position is more than the number of nodes, do nothing if (temp == NULL) { return; } // 5. If the node to be deleted is not the last node if (temp->next != NULL) { temp->next->prev = temp->prev; } // 6. If the node to be deleted is not the first node if (temp->prev != NULL) { temp->prev->next = temp->next; } // 7. Free the memory occupied by the deleted node free(temp); } // Function to print nodes in a given doubly linked list void printList(struct Node* node) { while (node != NULL) { printf("%d ", node->data); node = node->next; } printf("\n"); } int main() { struct Node* head = NULL; // Start with an empty list append(&head, 2); append(&head, 4); append(&head, 8); append(&head, 10); printf("Created DLL is: "); printList(head); // Output: 2 4 8 10 deleteAtPosition(&head, 2); // Delete node at position 2 printf("\nDLL after deleting at position 2: "); printList(head); // Output: 2 4 10 return 0; }
Output:
Created DLL is:
2 4 8 10
DLL after deleting at position 2:
2 4 10
Complexity Analysis of Doubly Linked List Operations
Operation | Time Complexity (Average) | Time Complexity (Worst) | Space Complexity |
Insertion | |||
– At Beginning | O(1) | O(1) | O(1) |
– At End | O(1) | O(1) | O(1) |
– Before Given Node | O(1) | O(1) | O(1) |
– After Given Node | O(1) | O(1) | O(1) |
Deletion | |||
– At Beginning | O(1) | O(1) | O(1) |
– At End | O(1) | O(1) | O(1) |
– At Given Position | O(n) | O(n) | O(1) |
Traversal | O(n) | O(n) | O(1) |
Search | O(n) | O(n) | O(1) |
Space Used (Overall) | – | – | O(n) |
Related FAQs:
1. What is a Doubly Linked List?
- A doubly linked list is a linear data structure where each node contains data and two pointers: one pointing to the next node and one pointing to the previous node.
- Doubly-linked lists offer more versatility in navigation and modification than singly-linked lists due to their bidirectional structure.
2. What are the Advantages of a Doubly Linked List over a Singly Linked List?
- Doubly linked lists allow for traversal in both directions, making it easier to access elements before a given node.
- They also enable more efficient deletion operations, especially when deleting a node given only a reference to that node.
3. What are the Disadvantages of a Doubly Linked List?
- The primary drawback is the increased memory usage caused by the additional “previous” pointer in each node.
- This can be a concern if memory usage is critical in your application.
4. What are Some Real-World Applications of Doubly Linked Lists?
Doubly linked lists are used in various applications, including:
- Navigation History in Browsers: The “back” and “forward” buttons rely on doubly linked lists to efficiently move between visited pages.
- Undo/Redo Functionality in Software: Storing a history of actions for undo/redo operations can be effectively implemented using a doubly linked list.
5. How Do You Insert and Delete Nodes in a Doubly Linked List?
- When inserting or deleting nodes in a doubly linked list, it’s crucial to meticulously update the “next” and “previous” pointers of the adjacent nodes.
- After each operation, it’s important to verify that the list’s connections are correct.