
- 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 2Case 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 10Case 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 10Case 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 8Case 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 10Complexity 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.
