Doubly Linked List
A linear data structure where each node contains a value and references to both the next and previous nodes, enabling bidirectional traversal.Overview
Doubly linked lists provide efficient insertion and deletion at both ends (O(1)) and support backward traversal. The trade-off is extra memory for the previous pointer.Implementation
Node Structure
Class Definition
API Reference
push(value: T): void
Adds an element to the end of the linked list.insert(value: T, index: number): void
Inserts a new element at the specified position.value: The value to insertindex: Position to insert at (0-based)
- Insert at head: O(1)
- Insert at tail: O(1)
- Insert at arbitrary position: O(n)
pop(): Node<T> | null
Removes and returns the last element from the linked list.at(index: number): Node<T> | null
Returns the element at the given index without removing it.remove(value: T): void
Removes the first occurrence of an element from the list.removeAt(index: number): void
Removes an element from the specified position in the list.- Remove at head: O(1)
- Remove at tail: O(1)
- Remove at arbitrary position: O(n)
isEmpty(): boolean
Returns true if the list is empty, false otherwise.toString(): string
Returns a string representation of the list.Complexity Summary
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| push | O(1) | O(1) |
| insert (head) | O(1) | O(1) |
| insert (tail) | O(1) | O(1) |
| insert (arbitrary) | O(n) | O(1) |
| pop | O(1) | O(1) |
| at | O(n) | O(1) |
| remove | O(n) | O(1) |
| removeAt (head) | O(1) | O(1) |
| removeAt (tail) | O(1) | O(1) |
| removeAt (arbitrary) | O(n) | O(1) |
| isEmpty | O(1) | O(1) |
| toString | O(n) | O(1) |
Comparison: Singly vs Doubly Linked List
| Feature | Singly Linked List | Doubly Linked List |
|---|---|---|
| Memory per node | 1 pointer | 2 pointers |
| Traversal | Forward only | Bidirectional |
| Insert at tail | O(n) | O(1) |
| Delete from tail | O(n) | O(1) |
| Delete with node reference | O(n) | O(1) |
| Implementation complexity | Simple | Moderate |
Key Characteristics
Advantages:
- Bidirectional traversal
- O(1) insertion/deletion at both ends
- O(1) deletion with node reference
- Easier implementation of certain algorithms
Use Cases
- Browser history: Forward and backward navigation
- Music player: Next/previous song functionality
- Undo/Redo: Bidirectional state navigation
- LRU Cache: Efficient removal and reordering
- Text editors: Cursor movement and editing
Implementation Details
Maintaining Both Pointers
When inserting a node, you must update:- The new node’s
nextandprevpointers - The previous node’s
nextpointer - The next node’s
prevpointer
Edge Cases to Handle
Empty List
Empty List
When inserting into an empty list, both
head and tail should point to the new node, and the node’s prev and next should be null.Single Element
Single Element
When removing the only element, set both
head and tail to null.Head/Tail Operations
Head/Tail Operations
Always check if you’re operating at boundaries and update both
head and tail pointers appropriately.Related Data Structures
Singly Linked List
Simpler alternative with forward-only traversal
Deque
Double-ended queue using doubly linked list