Doubly Linked List in C
A doubly linked list is a variation of a singly linked list, in which traversal through the list is possible in both directions: forward and backward. Each node in the list stores data, a pointer to the next node, and a pointer to the previous node.
What is a Doubly Linked List in C?
A Doubly Linked List is a complex data structure and is an advanced version of a Singly Linked List data structure. A doubly linked list is a linked data structure that consists of records called nodes that are linked together sequentially using pointers in the form of a chain. Each node in a doubly linked list stores the data, the pointer to the next node in the sequence, and the pointer to the previous node in the sequence. These pointers are named next and previous respectively. This pointer stores the memory address of the next and the previous pointer in the sequence. A special node pointer head is used to denote the start of a doubly linked list. The previous pointer in the head node and the next pointer in the last node of a doubly linked list points to a sentinel value or a terminator. In the C programming language, this sentinal value is the null pointer. We can perform many operations on a doubly linked list like the insertion of a new node into the list at a specific position, deletion of a node at a specified position from the list, and displaying the list from the head node till the end.
Components in a Doubly Linked List in C
For writing the doubly linked list program in C, we need to define the following components:
- Node - It is the basic unit of a doubly linked list. Nodes are linked together using pointers to create a doubly linked list. Each node stores the data item, the next pointer, and the previous pointer.
- Next Pointer - It stores the address of the next node in the sequence in a doubly linked list.
- Previous Pointer - It stores the address of the previous node in the sequence in a doubly linked list.
- Data - It stores the data value of the node.
- Head - It represents the start of the doubly linked list.
Operations on Doubly Linked List
Many operations can be performed on a doubly linked list. We will discuss the method and the implementation of each operation below, later in the article.
Traversing
Traversing means visiting each node of the linked list starting from the head pointer till the end of the list. This is usually done to perform a certain operation like displaying data of each node or searching for a node etc.
Insertion
We can insert a new node into a doubly linked list at any position. There are four main scenarios for inserting a node into a doubly linked list:
- Insertion at beginning: In this case, a new node is inserted in front of the doubly linked list. The Head pointer is updated to point to the newly added node.
- Insertion at end: In this case, a new node is inserted at the end of the doubly linked list. No changes are required to the head pointer.
- Insertion after a given node: In this case, given a pointer to a node in the doubly linked list, we need to insert the new node after the node whose pointer is given to us.
- Insertion before a given node: In this case, given a pointer to a node, the goal is to insert the new node before the node whose pointer is given.
Deletion
Deletion means removing a node from a doubly linked list and maintaining its structure after the operation. There are three cases for deleting a node from a doubly linked list:
- Deletion at beginning: The node at the beginning of the doubly linked list is removed. The head pointer is updated to point to the next node of the removed node. The node that is removed is deleted from the memory.
- Deletion at the end: The last node of the doubly linked list is removed.
- Deletion of the node at a given position: In this case, we need to delete the node at the specified position from the doubly linked list.
Searching
Searching for a node involves comparing the data of each node in a doubly linked list with the item given to be searched. Generally, the location of the node in the linked list or the address of the node is returned as output. This address can be used to access the same node if needed. If no such node is present, then NULL is returned as output.
C Program for Inserting a Node at the Front of the Doubly Linked List
Algorithm
The new node is added in front of the doubly linked list. This new node becomes the new head pointer.
- Step 1: Create a new node with the data item. Let's call this node as .
- Step 2 : Assign next pointer of to the head.
- Step 3: If the head pointer is not NULL, then assign the prev pointer of the head to the .
- Step 4: Finally update the head pointer.
Example
Consider a linked list with 3 nodes . Now we want to add the node with data 0 at the front.
First, we create a new node with data 0 and assign the next pointer of the new node to the head pointer.
Now, we assign the previous pointer of the head to the new node.
Finally, we update the head pointer.
Note: We pass a pointer to the head pointer in the function insertAtFront. If we do not do this, then the head pointer will get updated locally inside the function only.
Implementation
Complexity Analysis
Time Complexity -
To add a new node at the front, we are only updating a constant number of pointers, so the time complexity is .
Time Complexity:
Space Complexity -
To add a new node at the front, we only create the pointer to the new node. No additional memory is needed, so the space complexity is .
Space Complexity:
C Program for Inserting a Node at the End of the Doubly Linked List
Algorithm
To add a new node at the end of the doubly linked list, we first need to iterate to the end of the linked list and then add the new node.
- Step 1: Create a temporary pointer . Initialize it to the head pointer.
- Step 2: While is not NULL, move to the next node .
- Step 3: Now create a new node with the data .
- Step 4: Assign to the and assign to .
Example
Consider a linked list with 3 nodes . Now we want to add the node with data 4 at the end.
First, we go to the last node using a pointer and assign the next pointer of to the new node.
Now, we update the prev pointer of the new node.
Implementation
Complexity Analysis
Time Complexity -
When we add a new node to the end of the doubly linked list, we iterate from the head pointer to the last node, so the time complexity is , where is the number of nodes present in the list.
Time Complexity:
Space Complexity -
In the implementation, we use a constant amount of space for pointers and creating the object of the new node, so the space complexity is .
Space Complexity:
C Program for Inserting a Node in between Two Nodes of the Doubly Linked List
Algorithm
In this case, we are given a node after which we have to insert the new node.
- Step 1: Create a new node with the data given.
- Step 2: Assign to .
- Step 3: Assign to .
- Step 4: Assign to .
- Step 5: If is not NULL, then assign to .
Example
Consider a linked list with 3 nodes . Now we want to add the node with data 3 after the second node. We are also given the pointer to the second node.
We will first update the next pointer of the new node to the next pointer of the given node. Then, we assign the next pointer of the given node to the new node.
Finally, we update the prev pointers of the new node and the next node.
Implementation
Complexity Analysis
Time Complexity -
In the implementation, we are making a constant number of pointer changes, hence the complexity is .
Time Complexity:
Space Complexity -
In the implementation, we require a constant number of pointers and objects of the new node, so the space complexity is
.
Space Complexity:
C Program for Deleting a Node at the Beginning of the Doubly Linked List
Algorithm
- Step 1: Initialize a pointer to the pointer.
- Step 2: If pointer is not NULL, then increment the pointer.
- Step 3: Make the pointer as NULL and free the memory.
Example
Consider a linked list with 3 nodes . Now we want to delete the node at the front.
In this case, we simply update the head pointer to the next of the head pointer and delete the first node in the sequence.
Final Sequence:
Implementation
Complexity Analysis
Time Complexity -
In the implementation, we are updating the head pointer and deleting the node at the front, hence the time complexity is .
Time Complexity:
Space Complexity -
In the implementation, we are using only a constant amount of memory for pointer , hence the space complexity is .
Space Complexity:
C Program for Deleting a Code at the End of the Doubly Linked List
Algorithm
- Step 1: Initialize a pointer to the pointer.
- Step 2: While is not NULL, increment the pointer.
- Step 3: Update as NULL and as NULL.
- Step 4: Make the pointer as NULL and free the memory.
Example
Consider a linked list with 3 nodes . Now we want to delete the node at the end.
First, we iterate to the last node using a pointer . Now we assign as NULL.
Finally, we delete the curr node.
Implementation
Complexity Analysis
Time Complexity -
In the implementation, we are iterating till the end of the doubly linked list, hence the time complexity is .
Time Complexity:
Space Complexity -
In the implementation, we are using a constant number of pointers, hence the space complexity is .
Space Complexity:
C Program for Deleting a Node at a Specified Position of the Doubly Linked List
Algorithm
In this case, we have to delete the node at a specified index .
- Step 1: If is 1, then we delete the node at the front.
- Step 2: Iterate a pointer until .
- Step 3: Now we need to remove the node and connect and .
- Step 4: Assign to and to .
- Step 5: Make the pointer as NULL and free the memory.
Example
Consider a linked list with 3 nodes . Now we want to delete the second node in the list.
First, we go to the second node using a pointer .
Next, we connect the previous of the node and the next node of the node.
Finally, we delete the curr node.
Implementation
Complexity Analysis
Time Complexity -
In the implementation, we iterate until . In the worse case, we can end up iterating the whole list, hence the time complexity is where N is the number of nodes in the linked list.
Time Complexity:
Space Complexity -
In the implementation, we are only using a constant amount of space for the pointer, hence the space complexity is .
Space Complexity:
Menu Driven Program in C to Implement All the Operations of the Doubly Linked List
Output:
Conclusion
- Doubly linked list data structure stores the data, a pointer to the next node, and a pointer to the previous node in the sequence.
- The doubly linked list can be used to navigate in both forward and backward directions.
- In C, a doubly linked list is implemented using structures.
- A doubly linked list allows efficient insertion if the pointer to the node after which insertion takes place is given.
- A doubly linked list allows efficient deletion if the pointer to the node to be deleted is given.