Doubly Linked List in C++
Last Updated :
02 Jun, 2024
A Doubly Linked List (DLL) is a two-way list in which each node has two pointers, the next and previous that have reference to both the next node and previous node respectively. Unlike a singly linked list where each node only points to the next node, a doubly linked list has an extra previous pointer that allows traversal in both the forward and backward directions.
In this article, we will learn about the doubly linked list representation, implementation of doubly linked list in C++, basic operations that can be performed on doubly linked list, its advantages and disadvantages.
Doubly Linked List Representation in C++
In a doubly linked list, two pointers are maintained to keep track of the list i.e. head (that points to the first node) and tail (that points to the last node).
Doubly Linked ListImplementation of Doubly Linked List in C++
To implement all the basic operations that can be performed on a doubly linked list, we need to first define a node. Let's see how we can create a new node in a doubly linked list.
Creating a Node in Doubly Linked List in C++
Node-Doubly Linked ListEach node of a doubly linked list (DLL) consists of three fields:
- Item or Data: It is the value stored in the node.
- Next: A reference to the next node in the list.
- Previous: A reference to the last node in the list.
In C++, a node of a doubly linked list can be created using the below format:
class Node
{
public:
int data;
Node *next;
Node *prev;
};
Basic Operations on C++ Doubly Linked List
We can perform the following basic operations on a doubly linked list:
Operation | Description | Time Complexity | Space Complexity |
---|
Insertion at Beginning | This function is used to insert a new node at the beginning of the DLL. | O(1) | O(1) |
---|
Insertion at End | This function is used to insert a new node at the end of the DLL. | O(1) | O(1) |
---|
Insertion at Specific Position | This function is used to insert a new node at a specific position in the DLL. | O(n) | O(1) |
---|
Deletion from Beginning | This function is used to delete a node at the beginning of the DLL. | O(1) | O(1) |
---|
Deletion from End | This function is used to delete a node at the end of the DLL. | O(1) | O(1) |
---|
Deletion of Specific Node | This function is used to delete a node from a specific position of the DLL. Â | O(n) | O(1) |
---|
Forward Traversal | This function is used for traversing in a forward direction in a DLL. | O(n) | O(1) |
---|
Reverse Traversal | This function is used for traversing in a reverse direction in a DLL. | O(n) | O(1) |
---|
1. Insertion in Doubly Linked List in C++
In a doubly linked list, there are three ways in which the insertion operation can be performed:
- Insertion at the beginning of DLL
- Insertion at the end of DLL
- Insertion at Specific Position in DLL
a. Insertion at the Beginning in Doubly Linked List
Insertion at Beginning- Doubly Linked ListFirst, create a new node to be inserted and then follow the below approach to insert a new node at the beginning of a doubly linked list:
Approach:
- First, create a newNode
- If the list is empty:
- set newNode->next to NULL.
- set newNode->prev to NULL.
- point the head pointer to newNode.
- If the list is not empty:
- set newNode->next to head.
- set newNode->prev to NULL.
- set head->prev to newNode.
- point the head pointer to newNode.
b. Insertion at the End in Doubly Linked List
Insertion at End- Doubly Linked ListFirst, create a new node to be inserted and then follow the below approach to insert a new node at the end of a doubly linked list:
Approach:
- First, create a newNode.
- If the list is empty:
- set newNode->next to NULL.
- set newNode->prev to NULL.
- point the head pointer to newNode.
- If the list is not empty:
- find the last node by iterating the list (i.e. where last->next == NULL).
- set last->next to newNode.
- set newNode->prev to last.
- set newNode->next to NULL.
c. Insertion at Specific Position in Doubly Linked List
Insertion at Specific Position- Doubly Linked ListFirst, create a new node to be inserted and then follow the below approach to insert a new node at a given position in a doubly linked list:
Approach:
- First, create a newNode.
- Check whether the given position is valid or not by finding the size of the list.
- If the given position is 0 (or 1 depending on indexing):
- we can use the insertion at the beginning approach only.
- If the given position is the last i.e. it is equal to the size of the list:
- we can use the insertion at the end approach here.
- If the given position is valid then do the following:
- start traversing the list to find the node that comes immediately before the given position (call it prevNode).
- set newNode->next to prevNode->next.
- set newNode->prev to prevNode.
- if prevNode->next is not NULL, set prevNode->next->prev to newNode.
- set prevNode->next to newNode.
2. Deletion in Doubly Linked List in C++
Like insertion, there are three ways in which the deletion operation can be performed:
- Deletion at the beginning of DLL
- Deletion at the end of DLL
- Deletion at Specific Position in DLL
a. Deletion from the Beginning of Doubly Linked List
Deletion from Beginning- Doubly Linked ListTo delete a node from the beginning of the doubly linked list, follow the below approach:
Approach:
- First, check if the list is empty or not, if the list is empty then there's nothing to delete.
- if the list have only one node then:
- set head to NULL.
- free the memory of the node.
- if the list have more than one node:
- update the head by pointing it to head->next.
- set the prev of the new head to NULL.
- free the memory of the old head.
b. Deletion from the End of Doubly Linked List
Deletion from End- Doubly Linked ListTo delete a node from the end of a doubly linked list, follow the below approach:
Approach:
- First, check if the list is empty or not, if the list is empty there is nothing to delete.
- If the list is not empty then do the following:
- Find the last node by iterating through the list (i.e. where last->next == NULL).
- Then, check if the last node is the only node (head->next == NULL):
- just update the head to NULL.
- If more than one node:
- set the next of the second last node (last->prev) to NULL.
- Finally, free the memory of the last node.
c. Deletion From Specific Position of Doubly Linked List
Deletion from specific position- Doubly Linked ListTo delete a node from a specific position in a doubly linked list, follow the below approach:
Approach:
- If the given position is 0 (or 1 according to indexing), we can use deletion at the beginning.
- If the position is the last position, we can use deletion at the end.
- Check whether the given position is valid or not:
- If the given position is valid do the following:
- Start traversing the list to find the node to be deleted (delNode).
- If delNode is the first node, adjust the head.
- If not, point the delNode->prev->next to the next node (delNode->next) and delNode->next->prev to the previous node (delNode->prev).
- Finally, free the memory of the last node. node to be deleted.
3. Traversal in a Doubly Linked List in C++
Traversing a doubly linked list means iterating through the list by visiting each node and performing the desired operations. This can be done by maintaining a temp variable that starts from the head of the doubly linked list and follows the next pointer for traversing until the end of the list. In a doubly linked list, we can traverse in both directions:
- In forward traversal, traverse from the head to the tail node.
- In reverse traversal, traverse from the tail to the head node.
a. Forward Traversal in Doubly Linked List
To traverse the doubly linked list in the forward direction, follow the below approach:
Approach:
- First, create a temp pointer and copy the head pointer to it (temp = head).
- For traversing in a forward direction keep moving temp to temp -> next.
- We can perform the desired operation in each iteration.
b. Reverse Traversal in Doubly in Doubly Linked List
To traverse the doubly linked list in the reverse direction, follow the below approach:
Approach:
- First, create a temp pointer and copy the tail pointer to it. (temp = tail).
- For traversing in a backward direction keep moving the temp pointer to temp -> prev.
- We can perform the desired operation in each iteration.
C++ Program to Implement Doubly Linked List
The below program demonstrates the implementation of all the basic operations on the doubly linked list.
C++
// C++ program to Implement doubly linked list
#include <iostream>
using namespace std;
// Define a class named Node to represent a node in the
// doubly linked list.
class Node {
public:
// Data part of the node.
int data;
// Pointer to the next node.
Node* next;
// Pointer to the previous node.
Node* prev;
// Constructor to initialize the node with given data.
Node(int data)
{
this->data = data;
this->next = nullptr;
this->prev = nullptr;
}
};
// Function to insert a node at the beginning of the doubly
// linked list.
void insertAtBeginning(Node*& head, int data)
{
// Create a new node with the given data.
Node* newNode = new Node(data);
// Check if the doubly linked list is empty.
if (head == nullptr) {
head = newNode;
return;
}
// Update the next and previous pointers to insert the
// new node at the beginning.
newNode->next = head;
head->prev = newNode;
head = newNode;
}
// Function to insert a node at the end of the doubly linked
// list.
void insertAtEnd(Node*& head, int data)
{
// Create a new node with the given data.
Node* newNode = new Node(data);
// Check if the doubly linked list is empty.
if (head == nullptr) {
head = newNode;
return;
}
// Traverse to the last node of the list.
Node* temp = head;
while (temp->next != nullptr) {
temp = temp->next;
}
// Update the next and previous pointers to insert the
// new node at the end.
temp->next = newNode;
newNode->prev = temp;
}
// Function to insert a node at a specified position in the
// doubly linked list.
void insertAtPosition(Node*& head, int data, int position)
{
if (position < 1) {
cout << "Position should be >= 1." << endl;
return;
}
// If inserting at the head position.
if (position == 1) {
insertAtBeginning(head, data);
return;
}
// Create a new node with the given data.
Node* newNode = new Node(data);
Node* temp = head;
// Traverse to the node before the specified position.
for (int i = 1; temp != nullptr && i < position - 1;
i++) {
temp = temp->next;
}
// Check if the position is greater than the number of
// nodes.
if (temp == nullptr) {
cout << "Position greater than the number of nodes."
<< endl;
return;
}
// Update the next and previous pointers to insert the
// new node at the specified position.
newNode->next = temp->next;
newNode->prev = temp;
if (temp->next != nullptr) {
temp->next->prev = newNode;
}
temp->next = newNode;
}
// Function to delete a node from the beginning of the
// doubly linked list.
void deleteAtBeginning(Node*& head)
{
// Check if the doubly linked list is empty.
if (head == nullptr) {
cout << "The list is already empty." << endl;
return;
}
// Update the head pointer and delete the first node.
Node* temp = head;
head = head->next;
if (head != nullptr) {
head->prev = nullptr;
}
delete temp;
}
// Function to delete a node from the end of the doubly
// linked list.
void deleteAtEnd(Node*& head)
{
// Check if the doubly linked list is empty.
if (head == nullptr) {
cout << "The list is already empty." << endl;
return;
}
Node* temp = head;
// If there is only one node in the list.
if (temp->next == nullptr) {
head = nullptr;
delete temp;
return;
}
// Traverse to the last node of the list.
while (temp->next != nullptr) {
temp = temp->next;
}
// Update the previous pointer of the second last node
// and delete the last node.
temp->prev->next = nullptr;
delete temp;
}
// Function to delete a node from a specified position in
// the doubly linked list.
void deleteAtPosition(Node*& head, int position)
{
// Check if the doubly linked list is empty.
if (head == nullptr) {
cout << "The list is already empty." << endl;
return;
}
// If deleting the head node.
if (position == 1) {
deleteAtBeginning(head);
return;
}
Node* temp = head;
// Traverse to the node at the specified position.
for (int i = 1; temp != nullptr && i < position; i++) {
temp = temp->next;
}
// Check if the position is greater than the number of
// nodes.
if (temp == nullptr) {
cout << "Position is greater than the number of "
"nodes."
<< endl;
return;
}
// Update the next and previous pointers and delete the
// node at the specified position.
if (temp->next != nullptr) {
temp->next->prev = temp->prev;
}
if (temp->prev != nullptr) {
temp->prev->next = temp->next;
}
delete temp;
}
// Function to print the doubly linked list in forward
// direction.
void printListForward(Node* head)
{
Node* temp = head;
cout << "Forward List: ";
while (temp != nullptr) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
// Function to print the doubly linked list in reverse
// direction.
void printListReverse(Node* head)
{
Node* temp = head;
if (temp == nullptr) {
cout << "The list is empty." << endl;
return;
}
// Move to the end of the list.
while (temp->next != nullptr) {
temp = temp->next;
}
// Traverse backwards.
cout << "Reverse List: ";
while (temp != nullptr) {
cout << temp->data << " ";
temp = temp->prev;
}
cout << endl;
}
int main()
{
Node* head = nullptr;
// Demonstrating various operations on the doubly linked
// list.
// Insertion at End
insertAtEnd(head, 10);
insertAtEnd(head, 20);
// Insertion at beginning
insertAtBeginning(head, 5);
// Insertion at specific position
insertAtPosition(head, 15, 2);
// print the list
cout << "After Insertions:" << endl;
printListForward(head);
printListReverse(head);
// deletion from beginning
deleteAtBeginning(head);
// deletion from end
deleteAtEnd(head);
// deletion from specific position
deleteAtPosition(head, 2);
cout << "After Deletions:" << endl;
printListForward(head);
return 0;
}
OutputAfter Insertions:
Forward List: 5 15 10 20
Reverse List: 20 10 15 5
After Deletions:
Forward List: 15
Advantages of Doubly Linked List in C++
The following are the advantages of a doubly linked list in C++:
- The doubly linked list allows us to traverse in both forward and backward directions.
- The deletion of a node is more efficient and easy as it has a pointer to the previous node.
- It is easier to perform the reverse operation.
- A doubly linked list is dynamic in nature so it can grow or shrink in size.
Disadvantages of Doubly Linked List in C++
- It requires more memory than arrays, per node due to the additional storage used by the pointers.
- It is more complex to implement and maintain as compared to the singly-linked list.
- We have to traverse from the head node to the specific node for insertion and deletion at specific positions.
Similar Reads
Doubly Linked List in C
A doubly linked list is a type of linked list in which each node contains 3 parts, a data part and two addresses, one points to the previous node and one for the next node. It differs from the singly linked list as it has an extra pointer called previous that points to the previous node, allowing th
14 min read
Linked List in C++
In C++, a linked list is a linear data structure that allows the users to store data in non-contiguous memory locations. A linked list is defined as a collection of nodes where each node consists of two members which represents its value and a next pointer which stores the address for the next node.
10 min read
Doubly Linked List in Python
Doubly Linked List is a type of linked list in which each node contains a data element and two links pointing to the next and previous node in the sequence. This allows for more efficient operations such as traversals, insertions, and deletions because it can be done in both directions. Table of Con
13 min read
Circular Linked List in C++
A circular linked list is a linear data structure similar to a singly linked list where each node consists of two data members data and a pointer next, that stores the address of the next node in the sequence but in a circular linked list, the last node of the list points to the first node instead o
10 min read
Doubly Linked List meaning in DSA
A doubly linked list is a special type of linked list in which each node contains a pointer to the previous node as well as the next node in the structure. Characteristics of the Doubly Linked List: The characteristics of a doubly linked list are as follows: Dynamic size: The size of a doubly linked
3 min read
Why use a Doubly Linked List?
A doubly linked list is a type of data structure that allows for efficient insertion and deletion of elements at both ends. It is beneficial in scenarios where you need to traverse in both directions, and it provides greater flexibility compared to a singly linked list. What is Doubly Linked List ?A
3 min read
Introduction to Circular Doubly Linked List
A circular doubly linked list is defined as a circular linked list in which each node has two links connecting it to the previous node and the next node. Characteristics of Circular Doubly Linked List :A circular doubly linked list has the following properties: Circular: A circular doubly linked lis
4 min read
Circular Linked List in Python
A Circular Linked List is a variation of the standard linked list. In a standard linked list, the last element points to null, indicating the end of the list. However, in a circular linked list, the last element points back to the first element, forming a loop. In this article, we will discuss the c
13 min read
Linked List meaning in DSA
A linked list is a linear data structure used for storing a sequence of elements, where each element is stored in a node that contains both the element and a pointer to the next node in the sequence. Types of linked lists: Linked lists can be classified in the following categories Singly Linked List
4 min read
Introduction to Doubly Linked Lists in Java
Doubly linked list is a data structure that has reference to both the previous and next nodes in the list. It provides simplicity to traverse, insert and delete the nodes in both directions in a list. In a doubly linked list, each node contains three data members: data: The data stored in the nodene
11 min read