A linked list is one of the most basic data structures in computer science. In this article, we will go through the following topics:
It is a list of nodes where each node contains data and a pointer to the next node in the list. It is a linear data structure, meaning it can be traversed by following only one pointer at a time. The first node is called the head, and the last node is called the tail. The tail node points to null.
class Node:
def __init__(self, data: int, next_node: 'Node' = None):
self.data = data
self.next = next_node
There are three ways to insert a node in a linked list:
Let's start with the simplest one. We will insert a node at the beginning of the list. The algorithm consists of the following steps:
def insert_at_beginning(head: Node, data: int) -> Node:
new_node = Node(data)
new_node.next = head
return new_node
Let's create a list of 4 nodes with that method:
head = None
for i in range(4):
head = insert_at_beginning(head, i + 1)
The time complexity of this algorithm is O(1) because we are only changing the head pointer
That algorithm is a bit more complicated, but still an easy one. We will insert a node at the end of the list.
def insert_at_end(head: Node, data: int) -> Node:
new_node = Node(data)
if head is None:
return new_node
current = head
while current.next is not None:
current = current.next
current.next = new_node
return head
head = None
for i in range(5):
head = insert_at_end(head, i + 1)
The time complexity of this algorithm is O(n) because we are iterating through the list until we find the tail.
We will insert a node at a given position. The algorithm consists of the following steps:
def insert_at_position(head: Node, data: int, position: int) -> Node:
new_node = Node(data)
if position == 0:
new_node.next = head
return new_node
current = head
current_position = 0
while current is not None and current_position < position - 1:
current = current.next
current_position += 1
if current is None:
return head
new_node.next = current.next
current.next = new_node
return head
The time complexity of this algorithm is O(n) because we are iterating through the list until we find the node at the required position
Insert a node at position 0:
Insert a node at a position greater than the length of the list:
Insert a node at a position between 0 and the length of the list:
There are three ways to delete a node from a linked list:
The algorithm consists of the following steps:
def delete_first(head: Node) -> Node:
if head is None:
return None
return head.next
The time complexity of this algorithm is O(1) because we are only changing the head pointer.
The algorithm consists of the following steps:
def delete_last(head: Node) -> Node:
if head is None:
return None
if head.next is None:
return None
current = head
while current.next.next is not None:
current = current.next
current.next = None
return head
The time complexity of this algorithm is O(n) because we are iterating through the list until we find the second last node.
The algorithm consists of the following steps:
def delete_at_position(head: Node, position: int) -> Node:
if position == 0:
return head.next
current = head
current_position = 0
while current is not None and current_position < position - 1:
current = current.next
current_position += 1
if current is None or current.next is None:
return head
current.next = current.next.next
return head
The time complexity of this algorithm is O(n) because we are iterating through the list until we find the node at the required position.
In this article, we have seen how to implement a linked list in Python. That data structure is very efficient when you need to add or remove elements from the head of the list. It is also very easy to implement.