Types of Linked Lists
A linked list is a dynamic data structure where each element (node) contains data and a reference to the next node in the sequence. Linked lists are widely used in various algorithms and data manipulation tasks due to their flexibility and efficient memory usage.
There are three main types of linked lists:
Each type has its own unique properties and use cases, which we'll explore in detail.
A singly linked list is the simplest type of linked list. In a singly linked list, each node contains two parts:
The list starts with a head pointer, which points to the first node. Each node points to the next node, and the last node points to None
(null), indicating the end of the list.
None
class Node:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
def insert_at_end(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return
current = self.head
while current.next:
current = current.next
current.next = new_node
def traverse(self):
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# Example usage
ll = SinglyLinkedList()
ll.insert_at_end(10)
ll.insert_at_end(20)
ll.insert_at_end(30)
ll.traverse() # Output: 10 -> 20 -> 30 -> None
A doubly linked list is a more advanced version of the singly linked list. In this type of list, each node contains three parts:
The head points to the first node, and the tail points to the last node. The last node's next
pointer is None
, and the first node’s prev
pointer is None
.
prev
pointer, making it less memory-efficient than a singly linked list.next
and prev
pointers can make implementation more complex.
class Node:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class DoublyLinkedList:
def __init__(self):
self.head = None
def insert_at_end(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return
last_node = self.head
while last_node.next:
last_node = last_node.next
last_node.next = new_node
new_node.prev = last_node
def traverse_forward(self):
current = self.head
while current:
print(current.data, end=" <-> ")
current = current.next
print("None")
def traverse_backward(self):
current = self.head
while current and current.next:
current = current.next
while current:
print(current.data, end=" <-> ")
current = current.prev
print("None")
# Example usage
dll = DoublyLinkedList()
dll.insert_at_end(10)
dll.insert_at_end(20)
dll.insert_at_end(30)
dll.traverse_forward() # Output: 10 <-> 20 <-> 30 <-> None
dll.traverse_backward() # Output: 30 <-> 20 <-> 10 <-> None
A circular linked list is a variation of the linked list in which the last node's next
pointer points back to the head of the list, creating a circle. Circular linked lists can be either singly or doubly linked, but the key feature is that the last node points back to the first node.
prev
pointer points to the last node, creating a circular structure in both directions.None
.None
in a singly linked list).
class Node:
def __init__(self, data):
self.data = data
self.next = None
class CircularLinkedList:
def __init__(self):
self.head = None
def insert_at_end(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
new_node.next = self.head
return
current = self.head
while current.next != self.head:
current = current.next
current.next = new_node
new_node.next = self.head
def traverse(self):
current = self.head
if not current:
print("List is empty.")
return
while True:
print(current.data, end=" -> ")
current = current.next
if current == self.head:
break
print("... (circular)")
# Example usage
cll = CircularLinkedList()
cll.insert_at_end(10)
cll.insert_at_end(20)
cll.insert_at_end(30)
cll.traverse() # Output: 10 -> 20 -> 30 -> ... (circular)