Deleting a node in linked list: Beginning, End & Given location
- Algorithm
- C Code Implementation
- Algorithm
- C Code Implementation
- Algorithm
- C Code Implementation
- Linked List Deletion Methods Comparison
- Visual Deletion Examples
- Time Complexity of Linked List Operations
- Space Complexity of Linked List Operations
- Edge Cases & Error Handling of Deletion of Linked Lists
- Conclusion
Deletion in a singly linked list is the process of removing a node while keeping the structure of the list intact. Since each node contains data and a pointer to the next node, deleting any node requires updating the pointer links to bypass the node being removed. Depending on the position of the node—beginning, end, or a specific location—the steps and pointer adjustments vary. Proper deletion ensures efficient memory usage and prevents breaking the chain of connected nodes.
Delete Node from the Beginning of Linked List
Algorithm
- Check if list is empty → if yes, display error message
- Store current head node in temporary pointer
- Update head to point to second node (head = head→next)
- Free memory of original head node
- Display success message
C Code Implementation
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head = NULL;
struct node* createNode() {
struct node *newNode = (struct node *)malloc(sizeof(struct node));
if (newNode == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
newNode->next = NULL;
return newNode;
}
void insertNodeAtEnd() {
struct node *newNode, *temp;
newNode = createNode();
printf("Enter element to insert: ");
scanf("%d", &newNode->data);
if (head == NULL) {
head = newNode;
} else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
printf("Element inserted successfully!\n");
}
void deleteFromBeginning() {
if (head == NULL) {
printf("List is empty - nothing to delete\n");
return;
}
struct node *temp = head;
head = head->next;
printf("Deleted %d from beginning\n", temp->data);
free(temp);
}
void displayList() {
struct node *temp = head;
if (temp == NULL) {
printf("List is empty\n");
return;
}
printf("Linked List: ");
while (temp != NULL) {
printf("%d → ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int menu() {
int choice;
printf("\n1. Insert element at end");
printf("\n2. Delete from beginning");
printf("\n3. Display list");
printf("\n4. Exit");
printf("\nEnter choice: ");
scanf("%d", &choice);
return choice;
}
int main() {
printf("** Linked List Deletion Operations **\n");
while (1) {
switch (menu()) {
case 1: insertNodeAtEnd(); break;
case 2: deleteFromBeginning(); break;
case 3: displayList(); break;
case 4: exit(0);
default: printf("Invalid choice\n");
}
}
return 0;
}
Output
** Linked List Deletion Operations **
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 10
Element inserted successfully!
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 20
Element inserted successfully!
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 30
Element inserted successfully!
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 3
Linked List: 10 → 20 → 30 → NULL
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 2
Deleted 10 from beginning
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 3
Linked List: 20 → 30 → NULL
1. Insert element at end
2. Delete from beginning
3. Display list
4. Exit
Enter choice: 4
[Program terminates]
Delete Node from End of Linked List
Algorithm
- Check if list is empty → display error if empty
- If only one node → set head to NULL and free it
- If multiple nodes → traverse to second-last node
- Update second-last node’s next pointer to NULL
- Free memory of last node
C Code Implementation
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head = NULL;
struct node* createNode() {
struct node *newNode = (struct node *)malloc(sizeof(struct node));
if (newNode == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
newNode->next = NULL;
return newNode;
}
void insertNodeAtEnd() {
struct node *newNode, *temp;
newNode = createNode();
printf("Enter element to insert: ");
scanf("%d", &newNode->data);
if (head == NULL) {
head = newNode;
} else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
printf("Element inserted successfully!\n");
}
void deleteFromEnd() {
if (head == NULL) {
printf("List is empty - nothing to delete\n");
return;
}
struct node *temp = head;
struct node *prev = NULL;
// Traverse to last node
while (temp->next != NULL) {
prev = temp;
temp = temp->next;
}
if (prev == NULL) { // Only one node in list
head = NULL;
} else { // Multiple nodes
prev->next = NULL;
}
printf("Deleted %d from end\n", temp->data);
free(temp);
}
void displayList() {
struct node *temp = head;
if (temp == NULL) {
printf("List is empty\n");
return;
}
printf("Linked List: ");
while (temp != NULL) {
printf("%d → ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int menu() {
int choice;
printf("\n1. Insert element at end");
printf("\n2. Delete from end");
printf("\n3. Display list");
printf("\n4. Exit");
printf("\nEnter choice: ");
scanf("%d", &choice);
return choice;
}
int main() {
printf("** Delete from End of Linked List **\n");
while (1) {
switch (menu()) {
case 1: insertNodeAtEnd(); break;
case 2: deleteFromEnd(); break;
case 3: displayList(); break;
case 4: exit(0);
default: printf("Invalid choice\n");
}
}
return 0;
}
Output
** Delete from End of Linked List **
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 10
Element inserted successfully!
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 20
Element inserted successfully!
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 30
Element inserted successfully!
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 3
Linked List: 10 → 20 → 30 → NULL
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 2
Deleted 30 from end
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 3
Linked List: 10 → 20 → NULL
1. Insert element at end
2. Delete from end
3. Display list
4. Exit
Enter choice: 4
[Program terminates]
Delete Node at Specific Position
Algorithm
- Check if list is empty → display error if empty
- If position is 1 → delete from beginning
- Traverse to node at specified position
- Update previous node’s next pointer to skip target node
- Free memory of deleted node
- Handle invalid positions (beyond list length)
C Code Implementation
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head = NULL;
struct node* createNode() {
struct node *newNode = (struct node *)malloc(sizeof(struct node));
if (newNode == NULL) {
printf("Memory allocation failed!\n");
exit(1);
}
newNode->next = NULL;
return newNode;
}
void insertNodeAtEnd() {
struct node *newNode, *temp;
newNode = createNode();
printf("Enter element to insert: ");
scanf("%d", &newNode->data);
if (head == NULL) {
head = newNode;
} else {
temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
printf("Element inserted successfully!\n");
}
void deleteAtPosition() {
if (head == NULL) {
printf("List is empty - nothing to delete\n");
return;
}
int position, i;
printf("Enter position to delete (1-based indexing): ");
scanf("%d", &position);
if (position < 1) {
printf("Invalid position! Position must be >= 1\n");
return;
}
struct node *current = head;
struct node *previous = NULL;
// Special case: delete first node
if (position == 1) {
head = head->next;
printf("Deleted %d from position %d\n", current->data, position);
free(current);
return;
}
// Traverse to specified position
for (i = 1; current != NULL && i < position; i++) {
previous = current;
current = current->next;
}
if (current == NULL) {
printf("Position %d exceeds list length\n", position);
return;
}
// Unlink node from list
previous->next = current->next;
printf("Deleted %d from position %d\n", current->data, position);
free(current);
}
void displayList() {
struct node *temp = head;
if (temp == NULL) {
printf("List is empty\n");
return;
}
printf("Linked List: ");
while (temp != NULL) {
printf("%d → ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int menu() {
int choice;
printf("\n1. Insert element at end");
printf("\n2. Delete at specific position");
printf("\n3. Display list");
printf("\n4. Exit");
printf("\nEnter choice: ");
scanf("%d", &choice);
return choice;
}
int main() {
printf("** Delete at Specific Position **\n");
while (1) {
switch (menu()) {
case 1: insertNodeAtEnd(); break;
case 2: deleteAtPosition(); break;
case 3: displayList(); break;
case 4: exit(0);
default: printf("Invalid choice\n");
}
}
return 0;
}
Output
** Delete at Specific Position **
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 10
Element inserted successfully!
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 20
Element inserted successfully!
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 1
Enter element to insert: 30
Element inserted successfully!
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 3
Linked List: 10 → 20 → 30 → NULL
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 2
Enter position to delete (1-based indexing): 2
Deleted 20 from position 2
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 3
Linked List: 10 → 30 → NULL
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 2
Enter position to delete (1-based indexing): 5
Position 5 exceeds list length
1. Insert element at end
2. Delete at specific position
3. Display list
4. Exit
Enter choice: 4
[Program terminates]
Linked List Deletion Methods Comparison
| Aspect | Beginning Deletion | End Deletion | Position Deletion |
|---|---|---|---|
| Time Complexity | O(1) (constant) | O(n) (linear) | O(n) (worst-case) |
| Space Complexity | O(1) | O(1) | O(1) |
| Traversal Required | No | Yes (to find last) | Yes (to find position) |
| Special Cases | Empty list | Single node list | Invalid positions |
| Pointer Updates | Update head only | Update second-last’s next | Update previous node’s next |
Visual Deletion Examples
// Original list: 10 → 20 → 30 → 40 → NULL
// 1. Delete from beginning:
// Before: HEAD → 10 → 20 → 30 → 40 → NULL
// After: HEAD → 20 → 30 → 40 → NULL
// Result: 20 → 30 → 40 → NULL
// 2. Delete from end:
// Before: HEAD → 10 → 20 → 30 → 40 → NULL
// After: HEAD → 10 → 20 → 30 → NULL
// Result: 10 → 20 → 30 → NULL
// 3. Delete from position 2:
// Before: HEAD → 10 → 20 → 30 → 40 → NULL
// After: HEAD → 10 → 30 → 40 → NULL
// Result: 10 → 30 → 40 → NULL
Time Complexity of Linked List Operations
| Operation | Best Case | Average Case | Worst Case |
|---|---|---|---|
| Delete Beginning | O(1) | O(1) | O(1) |
| Delete End | O(1) (list empty) | O(n) | O(n) |
| Delete Position | O(1) (position = 1) | O(n/2) | O(n) |
| Insert at End | O(1) (list empty) | O(n) | O(n) |
| Display List | O(n) | O(n) | O(n) |
Space Complexity of Linked List Operations
| Operation | Space Complexity |
|---|---|
| Delete Beginning | O(1) |
| Delete End | O(1) |
| Delete Position | O(1) |
| Insert at End | O(1) |
| Display List | O(1) |
Edge Cases & Error Handling of Deletion of Linked Lists
// Edge cases to handle in deletion operations:
// 1. Empty list deletion
if (head == NULL) {
printf("Cannot delete - list is empty\n");
return;
}
// 2. Single node deletion (both beginning and end)
if (head->next == NULL) {
free(head);
head = NULL;
return;
}
// 3. Invalid position (negative or zero)
if (position < 1) {
printf("Invalid position - must be >= 1\n");
return;
}
// 4. Position exceeds list length
if (current == NULL) {
printf("Position %d exceeds list length\n", position);
return;
}
// 5. Memory allocation failure
if (newNode == NULL) {
printf("Memory allocation failed - cannot insert\n");
return;
}
Conclusion
Linked list deletion operations demonstrate the flexibility of dynamic data structures. Beginning deletion offers O(1) efficiency for queue-like behavior (FIFO), end deletion enables stack-like operations (LIFO), and position deletion provides random access removal capabilities. All deletion methods maintain O(1) space complexity while requiring careful pointer management to prevent memory leaks.
Key Considerations:
- Always check for empty list before deletion
- Properly free memory to prevent leaks
- Update pointers correctly to maintain list integrity
- Handle edge cases (single node, invalid positions)
- Use beginning deletion for maximum efficiency
Understanding these deletion patterns forms the foundation for implementing more complex data structures like stacks, queues, and deques using linked lists.