Core Module
12 min forge
Doubly Linked List
Explore bidirectional navigation in linked structures. Learn why two pointers are often better than one.
π Doubly Linked List: Bidirectional Power
A Doubly Linked List (DLL) is a complex version of a Singly Linked List where each node has two pointers: one pointing to the next node and one pointing to the previous node.
π‘ The Logic (ELI5)
Think of a Linked List as a Train:
- Singly Linked: You can walk from the engine to the caboose, but the doors only open one way. You can't walk back.
- Doubly Linked: Every car has a door to the car in front AND the car behind. You can walk back and forth as much as you want.
π The Deep Dive
Advantages over Singly Linked Lists
- Bidirectional Traversal: You can traverse from tail to head.
- Easier Deletion: If you have a reference to a node, you can delete it in $O(1)$ time because you already know its predecessor. In a Singly Linked List, you'd have to find the predecessor first ($O(n)$).
- Better for certain Data Structures: Essential for implementing Deques (Double Ended Queues) and LRU Caches.
The Cost
- Memory: Every node needs extra space for the
prevpointer (usually 8 bytes on 64-bit systems). - Complexity: Every insertion/deletion requires updating twice as many pointers. Fail to update one, and your list "breaks".
π οΈ Code Forge: DLL Implementation
javascript Standard/** * A Doubly Linked Node */ class DLLNode { constructor(value) { this.value = value; this.next = null; this.prev = null; // New pointer! } } /** * Basic DLL Operations */ class DoublyLinkedList { constructor() { this.head = null; this.tail = null; } // Insert at the end - O(1) append(value) { const newNode = new DLLNode(value); if (!this.head) { this.head = this.tail = newNode; return; } this.tail.next = newNode; newNode.prev = this.tail; this.tail = newNode; } // Delete a specific node - O(1) if you have the node reference deleteNode(node) { if (node.prev) node.prev.next = node.next; else this.head = node.next; if (node.next) node.next.prev = node.prev; else this.tail = node.prev; // Clean up pointers (optional) node.prev = node.next = null; } }
π― Interview Pulse
Key Use Cases
- Browser History: Moving forward and backward through pages.
- LRU Cache: Moving the "Most Recently Used" item to the front and removing the "Least Recently Used" from the back.
- Undo/Redo: Navigating states.
Common Questions
- Reverse a Doubly Linked List.
- Design an LRU Cache (The most common "Advanced" list question).
- Implement a Deque using a DLL.
- QuickSort and MergeSort on Doubly Linked Lists.