Linked lists
Nodes joined by next pointers trade cheap indexing for cheap insertion, at the cost of chasing memory.
Inserting in the middle of an array is expensive because everything after the insertion point must move. A linked list removes that cost by refusing to keep its elements together. Each element lives in its own node with a pointer to the next, so changing the chain means rewriting a pointer or two — at the price of losing random access entirely.
A treasure hunt, not a shelf
An array is a shelf: you can reach the seventh slot directly. A linked list is a treasure hunt: each clue tells you where the next one is. You can insert a clue by editing the previous one, but you cannot jump to the seventh clue without following six pointers.
Use the panel to prepend, append, remove the head and walk the chain. The cursor shows how traversal actually moves.
Insert, remove and walk the chain of next pointers
7
next 4
4
next None
head -> 7 -> 4 -> None
Press walk to place the cursor on the head.
Nothing is indexed: to find the third element you follow three pointers. Inserting at the head rewrites one pointer no matter how long the list is, but reaching the tail costs a full walk — the exact trade-off arrays make in reverse.
The node
A node is a tiny record: some data and a reference to the next node (or None
at the end). The list itself is just a reference to the head.
class Node:
def __init__(self, value, next=None):
self.value = value
self.next = next
class LinkedList:
def __init__(self):
self.head = None
def prepend(self, value):
self.head = Node(value, self.head) # O(1)prepend rewrites one pointer regardless of the list length, which is exactly
what an array cannot do.
The costs
- Prepend at the head: .
- Insert or delete after a known node: .
- Search / access index k: — you must walk.
- Append without a tail pointer: ; keep a tail reference to make it .
Notice the trade is the mirror image of the array: cheap anywhere insertion, expensive indexing. Neither is better; they are good at opposite things.
Variants
- A doubly linked list adds a
prevpointer, so you can delete a node given only the node itself, and traverse backward. Each node pays one extra pointer. - A circular list points the tail back at the head, useful for round-robin scheduling.
- A sentinel node at the front removes the special case of inserting into an empty list, simplifying the code.
Losing the head loses the list
If you reassign self.head without saving the old value, the rest of the
nodes become unreachable and are garbage-collected. In a doubly linked list,
forgetting to update both prev and next during a splice is the classic
source of subtle bugs — draw the pointers before you write the update.
Linked lists matter less in Python than in C because a Python list is already a fast dynamic array, but the pointer-chasing pattern behind them reappears in every tree and graph you will meet later.
Illustrative vs real
The walker shows a short chain of integers so the pointers fit on screen and are visible as arrows. Real nodes hold arbitrary objects and may be scattered across memory; that scattering is precisely why they are cache-unfriendly compared with a contiguous array. The asymptotic costs are unaffected.
Check yourself
Eduspheria wiki · Programming & Data Structures, Data structures
0 / 5 answered
From the assignment paper
Modeled on NITJ AI-507, Assignment/Quiz
0 / 5 answered
Where next: trees — imposing an order on linked nodes so search becomes logarithmic instead of linear.