Category: Sequence types
Topics: pointer manipulation, LRU caches, memory-constrained systems, dynamic memory allocation
A linear data structure where each element (node) contains data and a pointer to the next node, enabling efficient insertion and deletion without contiguous memory.
| Operation | Time Complexity | Description |
|---|---|---|
| Access | O(n) | Traverse from head to index |
| Search | O(n) | Linear scan through nodes |
| Insert (head) | O(1) | Update head pointer |
| Insert (tail) | O(n) or O(1)* | Traverse to end (*O(1) with tail pointer) |
| Insert (middle) | O(n) | Traverse to position, update pointers |
| Delete (head) | O(1) | Update head pointer |
| Delete (other) | O(n) | Traverse to find predecessor |
class Node:
def __init__(self, data):
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self):
self.head = None
def prepend(self, data):
"""Insert at head - O(1)"""
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def append(self, data):
"""Insert at tail - O(n)"""
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 delete(self, data):
"""Delete first occurrence - O(n)"""
if not self.head:
return
if self.head.data == data:
self.head = self.head.next
return
current = self.head
while current.next and current.next.data != data:
current = current.next
if current.next:
current.next = current.next.next
def search(self, data):
"""Search for value - O(n)"""
current = self.head
while current:
if current.data == data:
return True
current = current.next
return False
O(n) for n elements. Each node requires extra space for the next pointer (typically 8 bytes on 64-bit systems). No auxiliary space for operations.
Pros:
Cons: