doublyLinkedList.definition
doublyLinkedList.descriptionPart1
doublyLinkedList.descriptionPart2
doublyLinkedList.keyPointsTitle
- doublyLinkedList.keyPoint1
- doublyLinkedList.keyPoint2
- doublyLinkedList.keyPoint3
- doublyLinkedList.keyPoint4
doublyLinkedList.exampleTitle
null ←→ null
10doublyLinkedList.headLabel
⇆20
⇆30
⇆40doublyLinkedList.tailLabel
doublyLinkedList.syntaxTitle
// Java
class Node {
int value;
Node prev;
Node next;
Node(int value) {
this.value = value;
}
}
class DoublyLinkedList {
Node head;
Node tail;
void insert(int value) {
Node node = new Node(value);
if (head == null) {
head = tail = node;
} else {
tail.next = node;
node.prev = tail;
tail = node;
}
}
}# Python
class Node:
def __init__(self, value):
self.value = value
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def insert(self, value):
node = Node(value)
if not self.head:
self.head = self.tail = node
else:
self.tail.next = node
node.prev = self.tail
self.tail = node// C++
struct Node {
int value;
Node* prev;
Node* next;
Node(int v) : value(v), prev(nullptr), next(nullptr) {}
};
class DoublyLinkedList {
public:
Node* head = nullptr;
Node* tail = nullptr;
void insert(int value) {
Node* node = new Node(value);
if (!head) {
head = tail = node;
} else {
tail->next = node;
node->prev = tail;
tail = node;
}
}
};// JavaScript
class Node {
constructor(value) {
this.value = value;
this.prev = null;
this.next = null;
}
}
class DoublyLinkedList {
constructor() {
this.head = null;
this.tail = null;
}
insert(value) {
const node = new Node(value);
if (!this.head) {
this.head = this.tail = node;
} else {
this.tail.next = node;
node.prev = this.tail;
this.tail = node;
}
}
}Interactive Doubly Linked List Visualization
∅
List is empty. Insert a value to begin.
Size: 0
Node
Traversing
Found
Inserting
Rewiring
Removing
Note: Each node has both prev and next pointers. Insert at tail is O(1) with tail pointer. Remove/Search traverse from head O(n).
Time & Space Complexity
Doubly linked lists allow O(1) insertion/removal at both ends and enable backward traversal, at the cost of extra memory for the prev pointer.
| Operation | Time | Why? |
|---|---|---|
| Insert at Tail | O(1) | With tail pointer, directly append and update prev/next |
| Insert at Head | O(1) | Update head pointer and set new node's next to old head |
| Remove (by value) | O(n) | Traverse to find node, then O(1) to rewire pointers |
| Remove Head/Tail | O(1) | Direct access via head/tail pointers |
| Search | O(n) | Traverse nodes one by one (can go forward or backward) |
| Access by Index | O(n) | Must traverse from head or tail |
| Space | O(n) | Extra pointer (prev) per node compared to singly linked list |
vs Singly Linked List
- Advantage: Can traverse backward and remove tail in O(1)
- Advantage: Easier deletion when you have a pointer to the node
- Disadvantage: Extra memory per node for prev pointer
- Disadvantage: Slightly more complex insert/remove logic
doublyLinkedList.continueLearning
enhanced.author.title
enhanced.author.writtenBy:enhanced.author.teamName
enhanced.author.reviewedBy:enhanced.author.reviewerName
enhanced.author.lastUpdated:January 29, 2026