Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Doubly linked lists in Javascript
In this article, we are going to discuss a Doubly Linked List Class data structure in JavaScript. This is a linear data structure. Doubly linked lists are almost the same as a singly linked list in all operations, we just need to keep track of one extra link per node. In singly linked lists, we just had next links, in doubly linked lists, we have 2 links, next and prev.
Structure of Doubly Linked List
Doubly linked lists are represented as:
Note that in the class itself, we also need to keep track of the tail (last element) for efficient operations.
Node Structure
Each node contains three parts: previous pointer, data, and next pointer:
<!DOCTYPE html>
<html>
<body>
<script>
function createNode(value) {
return {
value: value,
next: null,
previous: null,
};
}
// Example node creation
let node = createNode(10);
console.log(node);
</script>
</body>
</html>
Complete Implementation
Here's the complete doubly linked list implementation with insertion, deletion, and traversal methods:
<!DOCTYPE html>
<html>
<body>
<script>
function createNode(value) {
return {
value: value,
next: null,
previous: null,
};
}
class DoublyLinkedList {
constructor() {
this.head = null;
this.tail = null;
this.size = 0;
}
// Insert at the end
insert(value) {
this.size++;
let newNode = createNode(value);
if (this.tail) {
this.tail.next = newNode;
newNode.previous = this.tail;
this.tail = newNode;
return newNode;
}
this.head = this.tail = newNode;
return newNode;
}
// Insert at the beginning
insertHead(value) {
this.size++;
let newNode = createNode(value);
if (this.head) {
this.head.previous = newNode;
newNode.next = this.head;
this.head = newNode;
return newNode;
}
this.head = this.tail = newNode;
return newNode;
}
// Insert at specific index
insertIndex(value, index) {
if (index >= this.size) {
throw new Error("Insert index out of bounds");
}
if (index === 0) {
return this.insertHead(value);
}
this.size++;
let currentNode = this.head;
for (let i = 0; i < index; i++) {
currentNode = currentNode.next;
}
let previousNode = currentNode.previous;
let newNode = createNode(value);
newNode.next = currentNode;
newNode.previous = previousNode;
previousNode.next = newNode;
currentNode.previous = newNode;
return newNode;
}
// Remove from the end
remove() {
if (this.tail) {
this.size--;
let removedTail = this.tail;
let beforeTail = this.tail.previous;
this.tail = beforeTail;
if (this.tail) {
this.tail.next = null;
} else {
this.head = null;
}
return removedTail;
}
return undefined;
}
// Print the list
print() {
document.write("The Elements in the Doubly Linked List are:<br>");
let current = this.head;
let output = "";
while (current) {
let prev = current.previous ? current.previous.value : "null";
let next = current.next ? current.next.value : "null";
output += `[${prev}] <- ${current.value} -> [${next}]<br>`;
current = current.next;
}
document.write(output);
}
}
// Example usage
let dLinkedList = new DoublyLinkedList();
dLinkedList.insert(7);
dLinkedList.insert(8);
dLinkedList.insert(9);
dLinkedList.insertHead(5);
document.write("<h3>Doubly Linked List Example</h3>");
dLinkedList.print();
document.write("<br>List size: " + dLinkedList.size);
</script>
</body>
</html>
Key Operations
The main operations in a doubly linked list include:
| Operation | Time Complexity | Description |
|---|---|---|
| Insert at end | O(1) | Add element to tail |
| Insert at head | O(1) | Add element to beginning |
| Insert at index | O(n) | Add element at specific position |
| Remove from end | O(1) | Remove tail element |
Advantages
Doubly linked lists provide several advantages over singly linked lists:
- Bidirectional traversal - can move forward and backward
- Efficient deletion - no need to traverse from head to find previous node
- Better for implementing stacks, queues, and deques
Conclusion
Doubly linked lists offer bidirectional navigation with previous and next pointers. While they use more memory than singly linked lists, they provide faster deletion and backward traversal capabilities.
