C
Deleting from list
Learn to delete elements from a linked list.
Deleting from a list
Deleting detaches a node from the list and returns its memory. Two cases exist: the node to delete is the head or it's in the middle/end.
When deleting the head: Node *tmp = head; head = head->next; free(tmp);. The new head is the old head's next. When deleting in the middle: a prev cursor stays one node behind the target; prev->next = cur->next; skips cur, then free(cur);. Updating the previous node's next keeps the chain intact. Deletion can be O(n) because finding the value requires traversal.
The list_remove function
A full delete function merges the two cases. First check head == NULL; an empty list has nothing to delete. Then if the head's value matches, delete the head.
Otherwise traverse with a prev and cur pair. When cur->data == value is found, prev->next = cur->next; skips cur, free(cur); releases memory, and head is returned. If the value isn't found, the list is returned unchanged. The function always returns the head; the caller must take it back with head = list_remove(head, 20);. This pattern is needed because the head may change.
Exercise Remove 20
Write Node *list_remove(Node *head, int value). If head == NULL return NULL. If head->data == value then tmp = head; head = head->next; free(tmp); return head;. Otherwise walk with prev = head; cur = head->next;; when cur->data == value do prev->next = cur->next; free(cur); return head;. In main prepend 30, 20, 10; call head = list_remove(head, 20);; list_print(head);; free every node.
Show example solution
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
Node *list_push_front(Node *head, int value) {
Node *n = malloc(sizeof(Node));
n->data = value;
n->next = head;
return n;
}
void list_print(Node *head) {
Node *cur = head;
while (cur != NULL) {
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
Node *list_remove(Node *head, int value) {
if (head == NULL) return NULL;
if (head->data == value) {
Node *tmp = head;
head = head->next;
free(tmp);
return head;
}
Node *prev = head;
Node *cur = head->next;
while (cur != NULL) {
if (cur->data == value) {
prev->next = cur->next;
free(cur);
return head;
}
prev = cur;
cur = cur->next;
}
return head;
}
int main(void) {
Node *head = NULL;
head = list_push_front(head, 30);
head = list_push_front(head, 20);
head = list_push_front(head, 10);
head = list_remove(head, 20);
list_print(head);
while (head) { Node *t = head; head = head->next; free(t); }
return 0;
}
Test yourself
-
What is updated when deleting a middle node?
- cur->data
- prev->next
- cur->next
- head->data
Show answer
prev->next — prev->next = cur->next skips cur.
-
Delete the head
Node *tmp = head; head = head->____; free(tmp);
Show answer
Node *tmp = head; head = head->next; free(tmp);
-
Delete cases
- empty list
- return NULL
- head matches
- head = head->next
- middle matches
- prev->next = cur->next
- not found
- return head
Next lesson: Stack and queue