12.3 Linked Lists in Python
A linked list is a collection of elements, called nodes, where each node contains a reference (or pointer) to the next node in the sequence. Linked lists are dynamic and can grow or shrink in size easily because nodes are not stored in contiguous memory locations.
There are two main types of linked lists:
- Singly Linked List: Each node points to the next node.
- Doubly Linked List: Each node points to both the next and the previous node.
12.3.1 Singly Linked List
In a singly linked list, each node contains two parts:
- Data: The value stored in the node.
- Next: A reference (or pointer) to the next node in the list.
Example: Implementing a Singly Linked List
class Node:
def __init__(self, data):
self.data = data # Store the data (value)
self.next = None # Store a reference to the next node (default is None)
class SinglyLinkedList:
def __init__(self):
self.head = None # The list starts empty
# Insert a new node at the beginning of the list
def insert_at_beginning(self, data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
# Insert a new node at the end of the list
def insert_at_end(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next:
current = current.next
current.next = new_node
# Print the linked list
def print_list(self):
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
# Example usage
sll = SinglyLinkedList()
sll.insert_at_beginning(3)
sll.insert_at_beginning(2)
sll.insert_at_end(4)
sll.insert_at_end(5)
sll.print_list() # Output: 2 -> 3 -> 4 -> 5 -> None
In this example:
- The
Node
class defines the structure of each node, withdata
holding the node's value andnext
pointing to the next node. - The
SinglyLinkedList
class allows us to manipulate the list by inserting new nodes at the beginning or end and printing the list.
Advantages of Singly Linked Lists:
- Dynamic size: Can grow or shrink easily.
- Efficient insertions/removals: Particularly at the beginning.
Disadvantages of Singly Linked Lists:
- No backward traversal: You can only traverse from the head to the tail.
- Random access is inefficient: Finding an element by index requires traversing the list.
12.3.2 Doubly Linked List
In a doubly linked list, each node contains three parts:
- Data: The value stored in the node.
- Next: A reference to the next node.
- Prev: A reference to the previous node.
This allows traversal in both directions.
Example: Implementing a Doubly Linked List
class Node:
def __init__(self, data):
self.data = data # Value of the node
self.next = None # Pointer to the next node
self.prev = None # Pointer to the previous node
class DoublyLinkedList:
def __init__(self):
self.head = None # List starts empty
# Insert a node at the beginning
def insert_at_beginning(self, data):
new_node = Node(data)
new_node.next = self.head
if self.head is not None:
self.head.prev = new_node
self.head = new_node
# Insert a node at the end
def insert_at_end(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
current = self.head
while current.next:
current = current.next
current.next = new_node
new_node.prev = current
# Print the list from head to tail
def print_list(self):
current = self.head
while current:
print(current.data, end=" <-> ")
current = current.next
print("None")
# Example usage
dll = DoublyLinkedList()
dll.insert_at_beginning(2)
dll.insert_at_end(3)
dll.insert_at_end(4)
dll.print_list() # Output: 2 <-> 3 <-> 4 <-> None
In this example:
prev
in each node allows traversal in both directions, forward (usingnext
) and backward (usingprev
).- The
DoublyLinkedList
class provides methods to insert nodes and print the list in a readable way.
Advantages of Doubly Linked Lists:
- Traversal in both directions.
- Easier deletion of nodes, especially when the node is in the middle.
Disadvantages of Doubly Linked Lists:
- More memory usage: Each node requires an extra pointer (
prev
). - Slightly more complex implementation than singly linked lists.
12.3.3 Summary
- Linked Lists: Dynamic data structures with nodes pointing to the next (and possibly previous) nodes. Suitable for dynamic memory allocation and efficient insertions/deletions.
- Singly Linked List: Each node points to the next node.
- Doubly Linked List: Each node points to both the next and previous nodes.
By understanding and implementing linked lists, you can efficiently solve problems involving dynamic data storage, hierarchical relationships, and sorted data management.