Doubly Linked List
Core idea: what if a linked list could look both ways?

- A doubly linked list gives every node two pointers:
- One to the previous node (
prev) and one to the next (next) - This means you can traverse the list in either direction
- One to the previous node (
- Each node stores three things:
prev,next, andelem
Sentinel Nodes
Rather than dealing with messy edge cases when inserting at the start or end, a doubly linked list uses two dummy nodes called sentinels:
header— sits before all real nodes,prevpoints toNonetrailer— sits after all real nodes,nextpoints toNone
Sentinel nodes hold no data:
- Exist so that every node has a predecessor and a successor
- Insertion and deletion logic is then clean and uniform
Insertion
To insert a new node q between node p and p’s successor:
- Create
q, settingq.prev = pandq.next = p.next - Update
p.next.prev = q - Update
p.next = q
Deletion
To remove node p:
- Let
predecessor = p.prevandsuccessor = p.next - Set
predecessor.next = successor - Set
successor.prev = predecessor - Deprecate
pby nulling out its links and element
Both of these functions work no matter where in the linked list they are used. This is because of the sentinel nodes removing the need to check for edge cases.
Performance
| Operation | Time |
|---|---|
| All standard list ops | O(1) |
| Space per position | O(1) |
| Total space for n elements | O(n) |
| Everything runs in constant time: |
- You always know the exact nodes you need to rewire
- No traversal is required