In this article, we will learn what is singly linked list is and its implementation using Python.
The singly linked list is a linear data structure in which each element of the list contains a pointer that points to the next element in the list. Each element in the singly linked list is called a node. Each node has two components: data and a pointer next which points to the next node in the list.
The first node of the list is called a head, and the last node of the list is called a tail. The last node of the list contains a pointer to the null. Each node in the list can be accessed linearly by traversing through the list from head to tail.
Singly Linked List Implementation in Python
from typing import Any
class Node:
def __init__(self, data: Any):
self.data = data
self.next = None
def __repr__(self) -> str:
return f"Node({self.data})"
class LinkedList:
def __init__(self):
self.head = None
def __iter__(self) -> Any:
node = self.head
while node:
yield node.data
node = node.next
def __len__(self) -> int:
return len(tuple(iter(self)))
def __repr__(self) -> str:
return "->".join([str(item) for item in self])
def __getitem__(self, index: int) -> Any:
if not 0 <= index < len(self):
raise ValueError("list index out of range.")
for i, node in enumerate(self):
if i == index:
return node
# Used to change the data of a particular node
def __setitem__(self, index: int, data: Any) -> None:
if not 0 <= index < len(self):
raise ValueError("list index out of range.")
current = self.head
for i in range(index):
current = current.next
current.data = data
def insert_tail(self, data: Any) -> None:
self.insert_nth(len(self), data)
def insert_head(self, data: Any) -> None:
self.insert_nth(0, data)
def insert_nth(self, index: int, data: Any) -> None:
if not 0 <= index <= len(self):
raise IndexError("list index out of range")
new_node = Node(data)
if self.head is None:
self.head = new_node
elif index == 0:
new_node.next = self.head # link new_node to head
self.head = new_node
else:
temp = self.head
for _ in range(index - 1):
temp = temp.next
new_node.next = temp.next
temp.next = new_node
def print_list(self) -> None: # print every node data
print(self)
def delete_head(self) -> Any:
return self.delete_nth(0)
def delete_tail(self) -> Any: # delete from tail
return self.delete_nth(len(self) - 1)
def delete_nth(self, index: int = 0) -> Any:
if not 0 <= index <= len(self) - 1: # test if index is valid
raise IndexError("List index out of range.")
delete_node = self.head # default first node
if index == 0:
self.head = self.head.next
else:
temp = self.head
for _ in range(index - 1):
temp = temp.next
delete_node = temp.next
temp.next = temp.next.next
return delete_node.data
def is_empty(self) -> bool:
return self.head is None
def reverse(self) -> None:
prev = None
current = self.head
while current:
# Store the current node's next node.
next_node = current.next
# Make the current node's next point backwards
current.next = prev
# Make the previous node be the current node
prev = current
# Make the current node the next node (to progress iteration)
current = next_node
# Return prev in order to put the head at the end
self.head = prev
def main():
linked_list = LinkedList()
linked_list.insert_head(input("Inserting 1st at head ").strip())
linked_list.insert_head(input("Inserting 2nd at head ").strip())
print("\nPrint list:")
linked_list.print_list()
linked_list.insert_tail(input("\nInserting 1st at tail ").strip())
linked_list.insert_tail(input("Inserting 2nd at tail ").strip())
print("\nPrint list:")
linked_list.print_list()
print("\nDelete head")
linked_list.delete_head()
print("Delete tail")
linked_list.delete_tail()
print("\nPrint list:")
linked_list.print_list()
print("\nReverse linked list")
linked_list.reverse()
print("\nPrint list:")
linked_list.print_list()
print("\nString representation of linked list:")
print(linked_list)
print("\nReading/changing Node data using indexing:")
print(f"Element at Position 1: {linked_list[1]}")
linked_list[1] = input("Enter New Value: ").strip()
print("New list:")
print(linked_list)
print(f"length of linked_list is : {len(linked_list)}")
if __name__ == "__main__":
main()
Output:
Inserting 1st at head 10
Inserting 2nd at head 20
Print list:
20->10
Inserting 1st at tail 30
Inserting 2nd at tail 40
Print list:
20->10->30->40
Delete head
Delete tail
Print list:
10->30
Reverse linked list
Print list:
30->10
String representation of linked list:
30->10
Reading/changing Node data using indexing:
Element at Position 1: 10
Enter New Value: 50
New list:
30->50
length of linked_list is : 2
Related Data Structures in Python
Stack Implementation in PythonQueue Implementation in Python
Deque Implementation in Python
Singly Linked List Implementation in Python
Doubly Linked List Implementation in Python
Circular Linked List Implementation in Python
PriorityQueue Implementation in Python
Circular Queue Implementation in Python
Binary Search Tree Implementation in Python
Stack Implementation Using Linked List in Python
Stack Implementation Using Doubly Linked List in Python
DSA
Python
Comments
Post a Comment