Delete Node in a Linked List
Understanding how to delete node in a linked list is a fundamental skill for anyone studying data structures, preparing for technical interviews, or building efficient software. That said, a linked list consists of nodes where each node holds data and a reference (or pointer) to the next node. Deleting a node requires adjusting these references so that the list remains intact without the removed element. This article walks through the concept, different deletion scenarios, step‑by‑step algorithms, code examples in popular languages, complexity analysis, and common pitfalls to avoid.
What Is a Linked List?
A linked list is a linear collection of elements called nodes. Unlike arrays, nodes are not stored in contiguous memory locations; each node contains:
- Data – the value stored in the node.
- Next pointer – a reference to the subsequent node (or
null/Nonefor the last node).
Because insertion and deletion only involve updating pointers, linked lists offer O(1) time complexity for these operations when the node to modify is already known, making them ideal for dynamic data sets where frequent insertions and deletions occur.
Why Deleting a Node Matters
When you delete node in a linked list, you must make sure:
- The predecessor node’s
nextpointer now points to the node that followed the deleted one (or tonullif the deleted node was the tail). - Memory occupied by the removed node is reclaimed (in languages with manual memory management) or becomes eligible for garbage collection (in managed languages).
- Edge cases such as deleting the head, the tail, or the only node in the list are handled correctly to avoid breaking the list or causing dangling pointers.
General Approach to Delete a Node
The deletion process can be broken into three logical steps:
- Locate the node to delete (or its predecessor, depending on the technique).
- Update the predecessor’s
nextpointer to bypass the node being removed. - Release the node (if necessary) and return the updated list head.
If you only have access to the node to be deleted (a common interview variant), you can copy the data from the next node into the current node and then bypass the next node. This works for all nodes except the tail; deleting the tail requires access to the previous node Took long enough..
Honestly, this part trips people up more than it should.
Deleting the Head Node
Removing the first element is the simplest case because the head reference itself must change Which is the point..
Algorithm
- Store the current head in a temporary variable (
temp). - Move the head pointer to
head->next. - Free or dereference
temp.
Edge Cases
- If the list is empty (
head == null), there is nothing to delete. - If the list contains a single node, after deletion the head becomes
null.
Deleting a Middle Node
A middle node has both a predecessor and a successor. The predecessor’s next must be redirected to the node after the target.
Algorithm (given predecessor)
- Let
prevbe the node before the target. - Set
prev->next = target->next. - Free
target.
Algorithm (given only the target node, not tail)
- Copy data from
target->nextintotarget. - Set
target->next = target->next->next. - Free the original
target->nextnode.
This trick works because you effectively replace the target with its successor and then delete the successor node.
Deleting the Tail Node
Removing the last node requires updating the predecessor’s next pointer to null. Since singly linked lists only provide forward traversal, you must locate the node preceding the tail Took long enough..
Algorithm
- Traverse the list while keeping track of
prevandcurr. - Stop when
curr->next == null(i.e.,curris the tail). - Set
prev->next = null. - Free
curr.
Edge Cases
- If the list has one node, the operation is identical to deleting the head.
- If the list is empty, no action is needed.
Handling Special Cases
| Situation | Action |
|---|---|
| Empty list | Return null (no deletion possible). |
| Deleting multiple occurrences | Repeat deletion until no matching nodes remain (or stop after first). |
| Single‑node list | Deleting head/tail results in an empty list (head = null). |
| Deleting non‑existent value | Traverse to end; if not found, return original list unchanged. |
| Deleting in a doubly linked list | Update both next and prev pointers of neighboring nodes. |
Implementation Examples
Below are concise implementations for deleting a node by value in a singly linked list. Each version follows the same logical steps but adapts to language‑specific syntax.
C++
struct Node {
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};
Node* deleteNode(Node* head, int key) {
// Empty list
if (!head) return nullptr;
// Delete head node
if (head->data == key) {
Node* temp = head;
head = head->next;
delete temp;
return head;
}
// Search for the node to delete
Node* curr = head;
while (curr->next && curr->next->data != key) {
curr = curr->next;
}
// If key not found
if (!curr->next) return head;
// Unlink the node
Node* temp = curr->next;
curr->next = temp->next;
delete temp;
return head;
}
Java
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public ListNode deleteNode(ListNode head, int key) {
if (head == null) return null;
// Delete head
if (head.val == key) {
return head.next;
}
ListNode curr = head;
while (curr.Think about it: next. Also, val ! next != null && curr.= key) {
curr = curr.
// Key not present
if (curr.next == null) return head;
// Bypass the node to delete
curr.next = curr.next.
#### Python
```python
class Node:
def __init__(self, data):
self.data = data
self.next = None
def delete_node(head, key):
# Empty list
if not head:
return None
# Delete head
if head.data == key:
return head.next
# Find node before the one to delete
curr = head
while curr.next and curr.next.Practically speaking, data ! = key:
curr = curr.
# Key not found
if not curr.next: