Singly Linked List Visualization
Insert
Delete
Access
Utils
Insert, delete, and traverse nodes - see pointers link elements one direction.
Time O(n) · Space O(n)
class SllNode:
"""A single node in the singly linked list."""
def __init__(self, val):
self.val = val
self.next = None
class SllList:
"""
Singly Linked List implementation.
Provides operations for adding, removing, searching, and
traversing elements in a one-directional linked structure.
"""
def __init__(self, val=None):
"""Initialize the list, optionally with a starting value."""
if val is not None:
self.head = SllNode(val)
self.len = 1
else:
self.head = None
self.len = 0
def __len__(self):
"""Return the number of nodes in the list."""
return self.len
def __str__(self):
"""String representation: head -> ... -> tail."""
values = [str(el) for el in self]
return " -> ".join(values)
def __repr__(self):
return str(self)
def __iter__(self):
"""Iterate over all values in the list."""
cur = self.head
while cur:
yield cur.val
cur = cur.next
def __bool__(self):
"""Return True if the list is not empty."""
return self.len > 0
def get_at(self, position) -> SllNode:
"""
Get the node at the specified position.
Raises IndexError if position is invalid.
"""
if position >= self.len or position < 0:
raise IndexError("Position is invalid.")
node = self.head
for _ in range(position):
node = node.next
return node
def add_left(self, val):
"""Add a new node with the given value at the head."""
new_head = SllNode(val)
new_head.next = self.head
self.head = new_head
self.len += 1
def add_right(self, val):
"""Add a new node with the given value at the tail."""
if not self:
self.head = SllNode(val)
else:
tail = self.get_at(self.len - 1)
tail.next = SllNode(val)
self.len += 1
def add_at(self, val, position):
"""
Insert a new node at the specified position.
Raises IndexError if position is out of bounds.
"""
if position > len(self) or position < 0:
raise IndexError("Invalid position to insert a value at.")
if position == 0:
return self.add_left(val)
if position == len(self):
return self.add_right(val)
before = self.get_at(position - 1)
after = before.next
before.next = SllNode(val)
before.next.next = after
self.len += 1
def remove_left(self):
"""
Remove and discard the head node.
Raises IndexError if list is empty.
"""
if not self:
raise IndexError("List is empty.")
self.head = self.head.next
self.len -= 1
def remove_right(self):
"""
Remove and discard the tail node.
Raises IndexError if list is empty.
"""
if not self:
raise IndexError("List is empty.")
if self.len == 1:
self.head = None
else:
before_tail = self.get_at(self.len - 2)
before_tail.next = None
self.len -= 1
def remove_at(self, position):
"""
Remove the node at the specified position.
Raises IndexError if list is empty or position is invalid.
"""
if not self:
raise IndexError("List is empty.")
if position < 0 or position >= self.len:
raise IndexError("Position is invalid.")
if position == 0:
return self.remove_left()
before = self.get_at(position - 1)
to_remove = before.next
before.next = before.next.next
to_remove.next = None
self.len -= 1
def traverse(self):
"""Return a list of all values in the list."""
cur = self.head
arr = []
while cur:
arr.append(cur.val)
cur = cur.next
return arr
def search_for(self, val):
"""
Search for a value in the list.
Returns the position if found, -1 otherwise.
"""
cur = self.head
pos = 0
while cur:
if cur.val == val:
return pos
pos += 1
cur = cur.next
return -1
def reverse_list(self):
"""Reverse the linked list in place."""
prev = None
cur = self.head
while cur:
# This one-liner only works in Python! - tuple unpacking evaluates all vars on right first
# cur.next, prev, cur = prev, cur, cur.next
# Standard approach - store 3 variables
next = cur.next
cur.next = prev
prev = cur
cur = next
self.head = prev
# Example usage:
if __name__ == "__main__":
# Create a new list
sll = SllList()
# Add elements
sll.add_right(10)
sll.add_right(20)
sll.add_right(30)
print(sll) # 10 -> 20 -> 30
# Add to head
sll.add_left(5)
print(sll) # 5 -> 10 -> 20 -> 30
# Add at position
sll.add_at(15, 2)
print(sll) # 5 -> 10 -> 15 -> 20 -> 30
# Search for a value
pos = sll.search_for(20)
print(f"Found 20 at position: {pos}") # Found 20 at position: 3
# Get value at position
node = sll.get_at(2)
print(f"Value at position 2: {node.val}") # Value at position 2: 15
# Remove elements
sll.remove_left()
print(sll) # 10 -> 15 -> 20 -> 30
sll.remove_right()
print(sll) # 10 -> 15 -> 20
# Reverse the list
sll.reverse_list()
print(sll) # 20 -> 15 -> 10
A singly linked list is a linear data structure where each node stores data and a pointer to the next node. Unlike arrays, linked lists allow efficient insertion and deletion without shifting elements, but do not support constant-time random access.
Each node contains a value and a reference to the next node. Insertion at the head is O(1). To insert or delete at a specific position, traverse from the head until you reach the target node, then update the pointers.