Skip to content

Commit 270db38

Browse files
Merge pull request #563 from subhahens/feature/doubly-linked-list
Add Doubly Linked List implementation in C
2 parents 8077ad1 + 8dc3654 commit 270db38

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
/*
5+
* insert_end : it takes the pointer to the head of the list and a data value.
6+
* It creates a new node and inserts it at the end of the doubly linked list.
7+
* If the list is empty, the new node becomes the head.
8+
* @param head: Pointer to the head pointer of the list
9+
* @param data: Data value to insert in the new node
10+
* @return: None
11+
*/
12+
13+
// Structure of a node in a doubly linked list
14+
struct Node {
15+
int data; // Data stored in the node
16+
struct Node* prev; // Pointer to the previous node
17+
struct Node* next; // Pointer to the next node
18+
};
19+
20+
// Function to create a new node
21+
struct Node* create_node(int data) {
22+
// Allocate memory for a new node
23+
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
24+
new_node->data = data; // Set the node's data
25+
new_node->prev = NULL; // Previous is NULL for a new node
26+
new_node->next = NULL; // Next is NULL for a new node
27+
return new_node; // Return the newly created node
28+
}
29+
30+
// Function to insert a node at the front (beginning) of the list
31+
void insert_front(struct Node** head, int data) {
32+
struct Node* new_node = create_node(data); // Create a new node
33+
34+
new_node->next = *head; // Make new node point to current head
35+
if (*head != NULL) {
36+
// If list is not empty, previous of current head becomes new node
37+
(*head)->prev = new_node;
38+
}
39+
*head = new_node; // Update head to point to new node
40+
}
41+
42+
// Function to insert a node at the end of the list
43+
void insert_end(struct Node** head, int data) {
44+
struct Node* new_node = create_node(data); // Create a new node
45+
46+
if (*head == NULL) {
47+
// If list is empty, new node becomes head
48+
*head = new_node;
49+
return;
50+
}
51+
52+
// Traverse to the last node
53+
struct Node* temp = *head;
54+
while (temp->next != NULL) {
55+
temp = temp->next;
56+
}
57+
58+
// Update links to insert new node at the end
59+
temp->next = new_node;
60+
new_node->prev = temp;
61+
}
62+
63+
// Function to insert a node at a specific position (1-based index)
64+
void insert_at_position(struct Node** head, int data, int pos) {
65+
if (pos <= 1 || *head == NULL) {
66+
// If position is 1 or list is empty, insert at front
67+
insert_front(head, data);
68+
return;
69+
}
70+
71+
struct Node* new_node = create_node(data); // Create new node
72+
struct Node* temp = *head;
73+
74+
// Traverse to the node after which new node will be inserted
75+
int i;
76+
for (i = 1; i < pos - 1 && temp->next != NULL; i++) {
77+
temp = temp->next;
78+
}
79+
80+
// Update links to insert the new node
81+
new_node->next = temp->next;
82+
new_node->prev = temp;
83+
84+
if (temp->next != NULL) {
85+
// If not inserting at the end, update previous pointer of next node
86+
temp->next->prev = new_node;
87+
}
88+
89+
temp->next = new_node; // Link previous node to new node
90+
}
91+
92+
// Helper function to delete a node using its pointer
93+
void delete_node_pointer(struct Node** head, struct Node* del_node) {
94+
if (*head == NULL || del_node == NULL) return; // Nothing to delete
95+
96+
if (*head == del_node) {
97+
// If deleting the head node, move head pointer to next node
98+
*head = del_node->next;
99+
}
100+
101+
if (del_node->next != NULL) {
102+
// Update previous pointer of next node
103+
del_node->next->prev = del_node->prev;
104+
}
105+
106+
if (del_node->prev != NULL) {
107+
// Update next pointer of previous node
108+
del_node->prev->next = del_node->next;
109+
}
110+
111+
free(del_node); // Free memory of deleted node
112+
}
113+
114+
// Function to delete a node by its value
115+
void delete_by_value(struct Node** head, int key) {
116+
struct Node* temp = *head;
117+
118+
// Search for the node containing the value
119+
while (temp != NULL && temp->data != key) {
120+
temp = temp->next;
121+
}
122+
123+
if (temp == NULL) {
124+
// Value not found in the list
125+
printf("Value %d not found in list.\n", key);
126+
return;
127+
}
128+
129+
// Delete the found node
130+
delete_node_pointer(head, temp);
131+
}
132+
133+
// Function to display the list from head to tail
134+
void display_forward(struct Node* head) {
135+
struct Node* temp = head;
136+
printf("Forward: ");
137+
while (temp != NULL) {
138+
printf("%d ", temp->data); // Print current node data
139+
temp = temp->next; // Move to next node
140+
}
141+
printf("\n");
142+
}
143+
144+
// Function to display the list from tail to head
145+
void display_reverse(struct Node* head) {
146+
if (head == NULL) {
147+
printf("Reverse: (empty list)\n");
148+
return;
149+
}
150+
151+
struct Node* temp = head;
152+
153+
// Move to the last node
154+
while (temp->next != NULL) {
155+
temp = temp->next;
156+
}
157+
158+
printf("Reverse: ");
159+
// Traverse reverse using prev pointer
160+
while (temp != NULL) {
161+
printf("%d ", temp->data);
162+
temp = temp->prev;
163+
}
164+
printf("\n");
165+
}
166+
167+
// Main function to demonstrate DLL operations
168+
int main() {
169+
struct Node* head = NULL; // Initialize empty list
170+
171+
// Insert nodes
172+
insert_end(&head, 10); // List: 10
173+
insert_end(&head, 20); // List: 10->20
174+
insert_front(&head, 5); // List: 5->10->20
175+
insert_at_position(&head, 15, 3); // List: 5->10->15->20
176+
insert_end(&head, 30); // List: 5->10->15->20->30
177+
178+
// Display the list in both directions
179+
display_forward(head); // Output: 5 10 15 20 30
180+
display_reverse(head); // Output: 30 20 15 10 5
181+
182+
// Delete a node by value
183+
delete_by_value(&head, 20); // Delete 20
184+
185+
// Display after deletion
186+
display_forward(head); // Output: 5 10 15 30
187+
188+
// Try deleting a non-existent value
189+
delete_by_value(&head, 100); // Output: Value 100 not found in list
190+
191+
return 0;
192+
}
193+
/*
194+
* Algorithm: Doubly Linked List (DLL)
195+
* Description: A Doubly Linked List is a data structure consisting of nodes,
196+
* where each node contains data and two pointers: 'prev' pointing
197+
* to the previous node and 'next' pointing to the next node. This
198+
* allows traversal in both forward and backward directions. Common
199+
* operations include insertion (front, end, or specific position),
200+
* deletion (by value or position), and traversal.
201+
* Time Complexity:
202+
* Insertion at beginning : O(1)
203+
* Insertion at end : O(n)
204+
* Insertion at position : O(n)
205+
* Deletion by value : O(n)
206+
* Traversal (forward/reverse) : O(n)
207+
* Space Complexity: O(n)
208+
* Advantages:
209+
* - Can traverse both directions
210+
* - Efficient deletion if node pointer is known
211+
* Disadvantages:
212+
* - Extra memory per node for prev pointer
213+
* - More pointer manipulation can lead to bugs
214+
* Author: subhahens
215+
*/

0 commit comments

Comments
 (0)