Doubly and circular linked lists
A backward pointer buys O(1) removal; joining the ends buys endless rotation.
Doubly linked lists
Each node holds prev as well as next. That second pointer costs memory and buys the operation singly linked lists cannot do: remove a node you hold a reference to, in O(1), without walking to find its predecessor.
function unlink(node) {
if (node.prev) node.prev.next = node.next;
if (node.next) node.next.prev = node.prev;
node.prev = node.next = null; // help the garbage collector
return node;
}
That single capability is why doubly linked lists sit at the heart of LRU caches, browser history, undo stacks, and the ready queues inside operating system schedulers.
They also traverse backwards, which makes them the natural fit for a text editor's cursor or a media playlist with "previous track".
Sentinel nodes — a permanent dummy head and tail — remove every null check from insertion and removal. Production implementations nearly always use them.
Circular linked lists
Point the tail's next back at the head. There is no end, so traversal must stop on a condition rather than on null:
let node = head;
do {
visit(node);
node = node.next;
} while (node !== head); // stop when you come back round
Circular lists model anything that cycles: round-robin scheduling, a turn-based game, a ring buffer of fixed capacity, the Josephus problem.
The hazard is obvious and still catches people — any while (node) loop over a circular list runs forever.
Choosing between them
| Need | Structure |
|---|---|
| Forward traversal, cheap head insert | Singly linked |
| Remove a known node in O(1), traverse both ways | Doubly linked |
| Endless rotation, round-robin | Circular |
| Random access by index | Not a linked list — use an array |
The memory argument
A doubly linked list of numbers spends two pointers plus object overhead per element — often several times the payload. An array of the same numbers is contiguous and cache-friendly. Unless you need O(1) removal by reference or genuinely unbounded growth without reallocation, the array wins on real hardware even where Big O says otherwise.