Singly Linked List
Imagine a treasure hunt. You start with one clue. That clue doesn't give you the treasure — it points you to the next clue. That next clue points to the one after that, and so on until the last clue says "X marks the spot."
A singly linked list works exactly like that. Each item — called a node — is a small box that holds two things: a value (the actual data) and a pointer (a sticky note pointing to the next box in the chain). The very last node's pointer says null — meaning the chain ends here.
The only entry point is the head pointer, which always points to the very first node. To reach any other node, you must follow the chain from the head, one node at a time.
How is this different from an array?
In an array, all boxes sit side-by-side in memory — you can jump directly to box number 5. In a linked list, the boxes can be scattered anywhere in memory. The only path between them is the pointer inside each node. This makes access slow, but makes adding and removing nodes at the front incredibly fast.
← → arrow keys to step · click elements to interact
Linked List Operations
Why is access \(O(n)\)?
Want the 4th node? There's no shortcut. You start at the head, follow its pointer to node 2, follow that to node 3, follow that to node 4. Every step costs one pointer-follow. If your list has 1,000 nodes and you want the last one, you follow 1,000 pointers. That's \(O(n)\) — it grows with the size of the list.
Compare that to an array: arr[999] is instant because the computer calculates the memory address directly. Linked lists give up that superpower in exchange for flexibility.
Why is inserting at the head \(O(1)\)?
Here's the magic. To add a new node at the front, you only need to do two things:
- Set the new node's pointer to point at the current head.
- Update the head pointer to point at the new node.
That's it — two pointer changes, regardless of how long the chain is. No shifting, no copying. The rest of the list doesn't even know anything happened.
Deleting a node
To delete a node from the middle of the list, you first need to find it — which costs \(O(n)\). Once you've found its predecessor, deletion itself is just one pointer change: make the predecessor point to the deleted node's successor. The actual removal is \(O(1)\), but the search to get there is \(O(n)\).
Complexity
When should you use a singly linked list?
- You're frequently inserting or deleting at the front of the collection
- You don't need random access by index
- You want to implement a stack or a simple queue
- The size of the data changes unpredictably and you don't want to allocate a large buffer
When should you avoid it?
- You frequently access elements by position — use an array instead
- You need to traverse both forwards and backwards — consider a doubly linked list
- Memory is tight — every node carries extra overhead for its pointer
Find Middle Node (Slow & Fast Pointers)
Quick check
Continue reading