Back to Data Structures & Algorithms
2026-01-098 min read

Delete from a Linked List (Data Structures & Algorithms)

Learn Delete from a Linked List (Data Structures & Algorithms) step by step with clear examples and exercises.

Why This Matters

In this full guide, we will delve into one of the fundamental operations in data structures and algorithms: deleting elements from a linked list. Mastering this operation is essential for various programming tasks, interviews, and real-world coding scenarios. Let's dive deeper into understanding and mastering this operation!

Prerequisites

Before diving into the core concept, it's crucial to have a solid understanding of:

  1. Basic Python syntax
  2. Data structures and algorithms concepts
  3. Linked lists data structure
  4. Basic linked list operations like traversal, insertion, and searching
  5. Familiarity with exception handling in Python (optional but recommended)
  6. Understanding of recursive functions (for those who want to explore a recursive solution)
  7. Knowledge of time and space complexity analysis (to evaluate the efficiency of algorithms)

If you're not familiar with these concepts, we recommend reviewing them before proceeding.

Core Concept

A linked list is a linear collection of data elements, called nodes, connected by references. Each node contains two essential components: data and a reference to the next node in the sequence. In Python, this can be represented as follows:

class Node:
def __init__(self, data=None):
self.data = data
self.next = None

def __repr__(self):
return f"Node({self.data})"

To create a linked list, we'll first define an empty head node and then add nodes to the list one by one. For example:

head = Node(1) # Creating the initial node with value 1
second = Node(2) # Creating the second node with value 2
third = Node(3) # Creating the third node with value 3
fourth = Node(4) # Creating the fourth node with value 4
fifth = Node(5) # Creating the fifth node with value 5

head.next = second
second.next = third
third.next = fourth
fourth.next = fifth

Now, we have a linked list with values 1 -> 2 -> 3 -> 4 -> 5. To delete an element from this list, we'll need to traverse the list and modify the references appropriately.

Traversing the Linked List

Traversing a linked list means iterating through each node in the sequence until we reach the end (or null). In Python, traversal can be achieved by using a loop or recursion. Here's an example of traversing the linked list using a loop:

def traverse_linked_list(node):
current = node
while current is not None:
print(current)
current = current.next

Worked Example

Let's consider a linked list: 1 -> 2 -> 3 -> 4 -> 5 and delete node with value 3.

def delete_node(node_to_delete):
if node_to_delete is head:
head = node_to_delete.next
return

current = head
while current.next != node_to_delete:
current = current.next

if current.next is None:
raise ValueError("Node not found in the list.")

current.next = node_to_delete.next

class LinkedList:
def __init__(self):
self.head = None

def add(self, data):
if not self.head:
self.head = Node(data)
else:
current = self.head
while current.next:
current = current.next
current.next = Node(data)

def delete(self, data):
deleted_node = None
if not self.head:
raise ValueError("List is empty.")

if self.head.data == data:
deleted_node = self.head
self.head = self.head.next
else:
current = self.head
while current.next and current.next.data != data:
current = current.next

if not current.next:
raise ValueError("Node not found in the list.")

deleted_node = current.next
current.next = deleted_node.next

def __repr__(self):
result = ""
current = self.head
while current:
result += f"{current} -> "
current = current.next
return result[:-3] # Remove the trailing '->'

linked_list = LinkedList()
linked_list.add(1)
linked_list.add(2)
linked_list.add(3)
linked_list.add(4)
linked_list.add(5)
print(linked_list) # Output: Node(1) -> Node(2) -> Node(3) -> Node(4) -> Node(5)
linked_list.delete(3)
print(linked_list) # Output: Node(1) -> Node(2) -> Node(4) -> Node(5)

Common Mistakes

  1. Forgetting to check if the head node is the one to be deleted: If you delete the head node without checking, you'll end up with a broken linked list. To avoid this, first check if the current node is the head before deleting it.
  1. Not updating the correct reference: When deleting a node, make sure to update the correct reference (the one pointing to the deleted node). If you forget to do so, the node will remain in the list, but it won't be accessible anymore.
  1. Not handling empty or single-node lists: Make sure your code can handle cases where the linked list is empty or contains only one node. In these situations, deleting a node would result in an error if not handled properly.
  1. Not checking for duplicate values: When searching for a node to delete, make sure to check for duplicates and delete all occurrences if necessary.
  1. Not handling exceptions gracefully: Make sure your code can handle exceptions such as ValueError when the node to be deleted is not found in the list.
  1. Using linear search for finding a node to delete: Using linear search (i.e., traversing the entire list) to find a specific node before deleting it can lead to poor performance, especially with large lists. To improve efficiency, use techniques like hashing or binary search if applicable.
  1. Not optimizing for edge cases: Make sure your code handles edge cases such as empty lists, single-node lists, and multiple occurrences of the node to be deleted efficiently.

Practice Questions

  1. Write a function to delete the first occurrence of a specific value from a given linked list.
  2. Implement a recursive solution for deleting a node with a given value from a linked list.
  3. Write a function to delete all occurrences of a specific value from a linked list in one pass.
  4. Write a function to search for a specific value in a linked list and return the node containing that value (without deleting it).
  5. Implement a function to reverse a given linked list.
  6. Write a function to merge two sorted linked lists into a single sorted linked list.
  7. Implement a function to find the middle node of a linked list.
  8. Write a function to determine if a linked list contains a cycle.
  9. Implement a function to delete a linked list (i.e., freeing all memory allocated for the nodes).
  10. Write a function to find the kth-to-last node in a linked list.
  11. Write a recursive function to count the number of nodes in a linked list.
  12. Implement a function to insert a new node at a specific position in a linked list.
  13. Write a function to remove all duplicates from a sorted linked list.
  14. Implement a function to merge k sorted linked lists into one sorted linked list.
  15. Write a function to find the intersection of two sorted linked lists.

FAQ

  1. What if the value to be deleted is not found in the linked list? In this case, your code should not modify the list and return an appropriate message or exception.
  2. Can I delete a node without knowing its address? Yes, you can delete a node by traversing the list until you find it. However, deleting nodes efficiently requires keeping track of addresses to avoid traversing the entire list for each operation.
  3. How can I implement a two-pass solution to delete all occurrences of a specific value from a linked list? In a two-pass approach, first traverse the list and count the number of occurrences of the target value. Then, create a new linked list with the remaining nodes (excluding the ones with the target value), and adjust the references accordingly to insert the deleted nodes back into their correct positions.
  4. How can I optimize my delete function to work in constant time? To achieve constant-time deletion, use a data structure like a doubly linked list or a hash table (e.g., Python's built-in dictionary) instead of a singly linked list. In a doubly linked list, each node has both a next and a previous pointer, allowing for efficient insertion, deletion, and traversal operations in constant time. With a hash table, you can achieve O(1) average-case time complexity for searching, inserting, and deleting elements.
  5. What is the space complexity of my delete function? The space complexity of your delete function is O(1), as it only requires additional space to store temporary variables (such as deleted_node in the example above). However, the overall space complexity of a linked list depends on the number of nodes and their data sizes. If you want to optimize space usage, consider using a compressed or sparse representation of the linked list when appropriate.
  6. How can I implement a delete operation that requires O(log n) time complexity? To achieve logarithmic-time deletion, use a balanced binary search tree (e.g., AVL tree or red-black tree) instead of a singly linked list. These data structures allow for efficient insertions, deletions, and searches with an average time complexity of O(log n). However, the space complexity is higher due to additional information required for maintaining balance.
  7. How can I implement a delete operation that requires O(1) amortized time complexity? To achieve constant-amortized time deletion, use a data structure like a skip list or a treap. Skip lists allow for efficient insertions, deletions, and searches with an average time complexity of O(log n), but the space complexity is higher due to the additional levels in the list. Treaps (tree-heaps) are self-balancing binary search trees that use a randomization technique to ensure balance, resulting in an amortized time complexity of O(log n) for insertions, deletions, and searches. However, the space complexity is still higher than that of a singly linked list due to the additional information required for maintaining balance.
Delete from a Linked List (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn