A linked list stores a sequence as separate nodes, each holding a value and a pointer to the next node, threaded together instead of packed in one memory block.
Core pieces
- Node: holds a value (the data) and a next reference to the following node.
- Last node’s
nextisNone(means “no object here”). - Head: reference to the first node; your only handle on the list. Lose it and you lose everything.
- Singly linked: each node knows only the node after it (walk forward only).
- Doubly linked: adds a
prevpointer (walk both ways); costs one extra pointer per node plus more bookkeeping on insert/delete.
Structure
head -> [10|next] -> [20|next] -> [30|next] -> None
Node class
class Node:
def __init__(self, value):
self.value = value
self.next = None
Key operations
- Traversal: keep
current, start at head,current = current.nextuntilNone. O(n) time, O(1) space. - Insert after a known node: set
new.next = node.nextfirst, thennode.next = new. Order matters or you lose the tail. - Delete after a known node:
node.next = node.next.next; garbage collector frees the skipped node. - push (front):
new.next = self.head, thenself.head = new. Reverses insertion order. - Search / access by position: walk from head; no indexing, no
list[3]. - Use
current is None(not==) to test for the end.
Big-O (singly linked)
| Operation | Time |
|---|---|
| Access head | O(1) |
| push / insert-after / delete-after (known node) | O(1) |
| Traverse / search / i-th by position | O(n) |
| Insert or delete at end | O(n) |
Rule: standing on the right node is O(1); first finding a node is O(n).
Array vs linked list
| Operation | Python list | Linked list |
|---|---|---|
| Read i-th by position | O(1) | O(n) |
| Search for value | O(n) | O(n) |
| Insert/delete at front or known node | O(n) | O(1) |
| Extra memory per item | none | one pointer (two if doubly) |
Reach for Python’s built-in list almost always (fast indexing, memory locality); linked lists underpin stacks, queues, trees, and graphs.
Gotchas
- Losing the head: don’t write
head = head.nextin a loop; walk with a separatecurrent. - Wrong pointer order on insert: point the new node at the rest before rewiring the old
next. - Forgetting
Noneat the end: a fresh node must startnext = Noneor loops run forever. - Using
==instead ofisto test for the end. - Assuming index access exists; the fourth node means four hops.