Linked List
Linked List
Time Complexity:
Operation Time Complexity
Insertion at Beginning O(1)
Insertion at End O(n)
Insertion in Middle O(n)
Deletion at Beginning O(1)
Deletion at End O(n)
Deletion in Middle O(n)
Search O(n)
Traversal O(n)
Space Complexity:
The space complexity of a linked list is O(n), where n is the number of nodes in the
list. Each node stores one element of data and a reference to the next node, so
memory usage grows linearly with the number of elements.
Algorithm :
Insertion at Beginning:
Step 1 : Create a new node.
Step 2 : Point the new node’s next reference to the current head.
Step 3 : Update the head to point to the new node.
Insertion at End:
Step 1 : Traverse to the last node.
Step 2 : Create a new node and point the current last node’s next to the new node.
Insertion in Middle:
Step 1 : Traverse the list to the desired position.
Step 2 : Insert the new node at that position by adjusting the pointers of the
previous and next nodes.
Deletion at Beginning:
Update the head to point to the second node.
Deletion at End:
Step 1 : Traverse the list to the second last node.
Step 2 : Update the second last node’s next to NULL, effectively removing the last
node.
Deletion in Middle:
Step 1 : Traverse to the desired node.
Step 2 : Adjust the previous node’s next reference to point to the node after the one
being deleted.
Traversal:
Traverse through the list and print all elements.
Function InsertAtEnd(value):
Create a new node with data = value
If head is NULL:
head = new_node
return
Traverse to the last node
last_node.next = new_node
Function DeleteAtBeginning():
If head is NULL:
Print "List is Empty"
return
head = head.next
Function DeleteAtEnd():
If head is NULL:
Print "List is Empty"
return
Traverse to the second last node
second_last.next = NULL
Function DeleteAtMiddle(position):
If head is NULL:
Print "List is Empty"
return
Traverse to the node before the position
current_node.next = current_node.next.next
Function Search(value):
Traverse the list and compare each node’s data with value
Return the position if found, otherwise -1
Function PrintList():
Traverse the list and print each node’s data
Singly Linked List Code:
#include <stdio.h>
#include <stdlib.h>
// Node structure
struct Node {
int data;
struct Node* next;
};
if (head == NULL) {
head = new_node;
printf("Inserted %d at the end\n", value);
return;
}
if (temp == NULL) {
printf("Position exceeds the length of the list.\n");
return;
}
new_node->next = temp->next;
temp->next = new_node;
free(temp);
if (temp == NULL) {
printf("Position exceeds the length of the list.\n");
return;
}
prev->next = temp->next;
free(temp);
if (temp == NULL) {
printf("List is Empty\n");
return;
}
printf("List: ");
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int main() {
int choice, value, position;
while (1) {
printf("\nLinked List Menu:\n");
printf("1. Insert at Beginning\n");
printf("2. Insert at End\n");
printf("3. Insert at Middle\n");
printf("4. Delete from Beginning\n");
printf("5. Delete from End\n");
printf("6. Delete from Middle\n");
printf("7. Search for an Element\n");
printf("8. Print the List\n");
printf("9. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
if (choice == 1) {
printf("Enter value to insert at the beginning: ");
scanf("%d", &value);
insertAtBeginning(value);
} else if (choice == 2) {
printf("Enter value to insert at the end: ");
scanf("%d", &value);
insertAtEnd(value);
} else if (choice == 3) {
printf("Enter position to insert at: ");
scanf("%d", &position);
printf("Enter value to insert: ");
scanf("%d", &value);
insertAtMiddle(position, value);
} else if (choice == 4) {
deleteAtBeginning();
} else if (choice == 5) {
deleteAtEnd();
} else if (choice == 6) {
printf("Enter position to delete from: ");
scanf("%d", &position);
deleteAtMiddle(position);
} else if (choice == 7) {
printf("Enter value to search: ");
scanf("%d", &value);
search(value);
} else if (choice == 8) {
printList();
} else if (choice == 9) {
printf("Exiting the program.\n");
break;
} else {
printf("Invalid choice! Please try again.\n");
}
}
return 0;
}
Doubly Linked List
A Doubly Linked List (DLL) is a type of linked list where each node contains three
parts: The data, A pointer to the next node, A pointer to the previous node.
This structure allows bidirectional traversal, i.e., both forward and backward
movement through the list.
Time Complexities
Operation Time Complexity
Traversal O(n)
Insertion (front) O(1)
Insertion (end) O(1) if tail used, else O(n)
Insertion (middle) O(n)
Deletion (front) O(1)
Deletion (end) O(1) if tail used, else O(n)
Deletion (middle) O(n)
Search O(n)
Space Complexity: O(n) — each node has two pointers (prev and next)
Algorithm
Insertion at Beginning:
1. Allocate memory for new node.
2. Set its data.
3. Set next of new node to current head.
4. Set prev of head to new node (if head exists).
5. Update head to new node.
Insertion at End:
1. Allocate new node, set data.
2. Traverse to the last node.
3. Set next of last node to new node.
4. Set prev of new node to last node.
Deletion at Beginning:
1. Set head to head’s next.
2. Free previous head node.
3. Set new head’s prev to NULL.
Deletion at End:
1. Traverse to last node.
2. Set second last node’s next to NULL.
3. Free last node.
InsertAtEnd(data):
newNode ← allocate node
newNode.data ← data
newNode.next ← NULL
If head == NULL then
newNode.prev ← NULL
head ← newNode
Else
temp ← head
While temp.next ≠ NULL
temp ← temp.next
temp.next ← newNode
newNode.prev ← temp
DeleteFromBeginning():
If head == NULL then
Print "List is empty"
Else
temp ← head
head ← head.next
If head ≠ NULL then
head.prev ← NULL
Free temp
struct Node {
int data;
struct Node* prev;
struct Node* next;
};
void deleteFromBeginning() {
if (head == NULL) return;
struct Node* temp = head;
head = head->next;
if (head != NULL) {
head->prev = NULL;
}
free(temp);
}
void deleteFromEnd() {
if (head == NULL) return;
struct Node* temp = head;
if (temp->next == NULL) {
head = NULL;
free(temp);
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
temp->prev->next = NULL;
free(temp);
}
void displayForward() {
struct Node* temp = head;
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
void displayBackward() {
struct Node* temp = head;
if (temp == NULL) return;
while (temp->next != NULL) {
temp = temp->next;
}
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->prev;
}
printf("\n");
}
int main() {
insertAtBeginning(10);
insertAtBeginning(20);
insertAtEnd(5);
insertAfterValue(10, 15);
displayForward(); // 20 10 15 5
displayBackward(); // 5 15 10 20
deleteByValue(10);
deleteFromEnd();
deleteFromBeginning();
displayForward(); // 15
return 0;
}
Circular Linked List:
A Circular Linked List (CLL) is a variation of a linked list where the last node points
back to the first node, forming a circle. It can be singly or doubly linked, but this
overview covers singly circular linked list.
In a singly circular linked list, each node contains: Data, A pointer to the next node,
The last node’s next pointer points to the head node instead of NULL.
Time Complexities
Operation Time Complexity
Traversal O(n)
Insertion at Front O(n) (without tail), O(1) (with tail)
Insertion at End O(n) (without tail), O(1) (with tail)
Deletion at Front O(n) (without tail), O(1) (with tail)
Deletion at End O(n)
Deletion by Value O(n)
Search O(n)
Algorithm
Insertion at Beginning
1. Allocate node, set data.
2. If list is empty:
Point node’s next to itself.
Set head to node.
3. Else:
Traverse to last node.
Point new node’s next to head.
Point last node’s next to new node.
Set head to new node.
Insertion at End
1. Allocate node, set data.
2. If list is empty:
Point node’s next to itself.
Set head to node.
3. Else:
Traverse to last node.
Point last node’s next to new node.
Point new node’s next to head.
Deletion at Beginning
1. If list empty, return.
2. If one node:
Free node
Set head to NULL.
3. Else:
Traverse to last node.
Set head to head->next.
Set last->next to new head.
Free old head.
Deletion at End
1. If list empty, return.
2. If one node:
Free node
Set head to NULL.
3. Else:
Traverse to second last node.
Free last node.
Set second last’s next to head.
Traversal
Start from head and keep going to next until reaching head again.
Pseudocode
InsertAtBeginning(data):
newNode ← allocate
newNode.data ← data
If head == NULL then
newNode.next ← newNode
head ← newNode
Else
temp ← head
While temp.next ≠ head
temp ← temp.next
newNode.next ← head
temp.next ← newNode
head ← newNode
InsertAtEnd(data):
newNode ← allocate
newNode.data ← data
If head == NULL then
newNode.next ← newNode
head ← newNode
Else
temp ← head
While temp.next ≠ head
temp ← temp.next
temp.next ← newNode
newNode.next ← head
DeleteFromBeginning():
If head == NULL then return
If head.next == head then
Free head
head ← NULL
Else
temp ← head
While temp.next ≠ head
temp ← temp.next
temp.next ← head.next
Free head
head ← temp.next
struct Node {
int data;
struct Node* next;
};
void deleteFromBeginning() {
if (head == NULL) return;
if (head->next == head) {
free(head);
head = NULL;
return;
}
struct Node* temp = head;
struct Node* last = head;
while (last->next != head) {
last = last->next;
}
head = head->next;
last->next = head;
free(temp);
}
void deleteFromEnd() {
if (head == NULL) return;
if (head->next == head) {
free(head);
head = NULL;
return;
}
struct Node* temp = head;
struct Node* prev = NULL;
while (temp->next != head) {
prev = temp;
temp = temp->next;
}
prev->next = head;
free(temp);
}
void display() {
if (head == NULL) return;
struct Node* temp = head;
do {
printf("%d ", temp->data);
temp = temp->next;
} while (temp != head);
printf("\n");
}
int main() {
insertAtBeginning(30);
insertAtBeginning(20);
insertAtEnd(40);
insertAtEnd(50);
display(); // 20 30 40 50
deleteFromBeginning();
deleteFromEnd();
display(); // 30 40
return 0;
}
Doubly Circular Linked List:
A Doubly Circular Linked List (DCLL) is a type of linked list in which each node has
three parts: data, a pointer to the next node, and a pointer to the previous node.
The last node's next points to the head, and the head's prev points to the last node,
forming a closed loop in both directions.
Time Complexities
Operation Time Complexity
Traversal (forward) O(n)
Traversal (reverse) O(n)
Insertion at Front O(1)
Insertion at End O(1)
Deletion at Front O(1)
Deletion at End O(1)
Deletion by Value O(n)
Search O(n)
Insertion at End
1. Allocate a new node and assign it the given data.
2. If the list is empty:
Set the node’s next and prev to itself.
Make this node the head.
3. Else :
Identify the last node (tail) using head->prev.
Set the new node’s next to head.
Set the new node’s prev to tail.
Update tail->next to point to the new node.
Update head->prev to point to the new node.
The head remains unchanged.
Deletion at Beginning
1. If list empty, return.
2. If one node: Free and set head to NULL.
3. Else:
Update head and pointers.
Free old head.
Deletion at End
1. If the list is empty (head == NULL) : there is nothing to delete — exit.
2. If the list has only one node (head->next == head):
Free the head node.
Set head = NULL.
3. Else :
Identify the last node (tail) using head->prev.
Identify the second last node using tail->prev.
Set second_last->next = head.Set head->prev = second_last.
Free the tail node.
Pseudocode
InsertAtBeginning(data):
newNode ← allocate
newNode.data ← data
If head == NULL then
newNode.next ← newNode
newNode.prev ← newNode
head ← newNode
Else
tail ← head.prev
newNode.next ← head
newNode.prev ← tail
tail.next ← newNode
head.prev ← newNode
head ← newNode
InsertAtEnd(data):
newNode ← allocate
newNode.data ← data
If head == NULL then
newNode.next ← newNode
newNode.prev ← newNode
head ← newNode
Else
tail ← head.prev
newNode.next ← head
newNode.prev ← tail
tail.next ← newNode
head.prev ← newNode
DeleteFromBeginning():
If head == NULL then return
If head.next == head then
Free head
head ← NULL
Else
tail ← head.prev
temp ← head
head ← head.next
head.prev ← tail
tail.next ← head
Free temp
Doubly Circular Linked List :
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void deleteFromBeginning() {
if (head == NULL) return;
if (head->next == head) {
free(head);
head = NULL;
return;
}
struct Node* tail = head->prev;
struct Node* temp = head;
head = head->next;
head->prev = tail;
tail->next = head;
free(temp);
}
void deleteFromEnd() {
if (head == NULL) return;
if (head->next == head) {
free(head);
head = NULL;
return;
}
struct Node* tail = head->prev;
struct Node* prev = tail->prev;
prev->next = head;
head->prev = prev;
free(tail);
}
void displayForward() {
if (head == NULL) return;
struct Node* temp = head;
do {
printf("%d ", temp->data);
temp = temp->next;
} while (temp != head);
printf("\n");
}
void displayBackward() {
if (head == NULL) return;
struct Node* tail = head->prev;
struct Node* temp = tail;
do {
printf("%d ", temp->data);
temp = temp->prev;
} while (temp != tail);
printf("\n");
}
int main() {
insertAtBeginning(30);
insertAtBeginning(20);
insertAtEnd(40);
insertAtEnd(50);
displayForward(); // 20 30 40 50
displayBackward(); // 50 40 30 20
deleteFromBeginning();
deleteFromEnd();
displayForward(); // 30 40
displayBackward(); // 40 30
return 0;
}