A chain of nodes where each element points to the next β trading indexed access for O(1) insertion anywhere you hold a pointer.
A linked list stores each element in its own node with a pointer to the next node. There's no index arithmetic β reaching position i means walking i pointers, O(n). In exchange, inserting or removing a node where you already hold a reference is O(1) with no shifting. Doubly linked lists add a previous-pointer so you can also walk and delete backwards.
Step through linked lists live, one move at a time β this becomes a fully interactive visualizer.
Coming soonnext pointer; the list keeps a reference to the head.head and follow next until you hit null.p: point the new node at p.next, then point p.next at the new node β two pointer writes, O(1).p: set p.next = p.next.next β the skipped node is unlinked.prev pointers, enabling O(1) delete of a node you hold directly.function reverse(head) {
let prev = null;
let curr = head;
while (curr !== null) {
const next = curr.next; // save the rest
curr.next = prev; // flip the pointer
prev = curr; // advance prev
curr = next; // advance curr
}
return prev; // new head
}Floyd's tortoise-and-hare: advance one pointer by 1 and another by 2. If they ever meet, there's a cycle; if the fast pointer reaches null, there isn't. O(n) time, O(1) space.
Cache locality. Array elements sit next to each other so the CPU prefetches them; list nodes scatter across the heap, causing a cache miss per hop. The O(1) insert only wins when insertions dominate.
Queues and deques with O(1) ends, LRU caches (doubly linked list + hash map), and any structure where you splice ranges or delete known nodes constantly without needing indexed access.
Share what clicked for you and see notes from other learners on this topic.
Coming soon