class Node {
constructor(data) {
this.data = data;
this.prev = null;
this.next = null;
}
}
class DoublyLinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
// Add a node to the end of the list
append(data) {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
newNode.prev = this.tail;
this.tail = newNode;
}
this.length++;
return this;
}
// Add a node to the beginning of the list
prepend(data) {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
this.tail = newNode;
} else {
newNode.next = this.head;
this.head.prev = newNode;
this.head = newNode;
}
this.length++;
return this;
}
// Insert a node at a specific index
insert(index, data) {
if (index < 0 || index > this.length) {
return false; // Or throw an error
}
if (index === 0) {
return this.prepend(data);
}
if (index === this.length) {
return this.append(data);
}
const newNode = new Node(data);
let leader = this.traverseToIndex(index - 1);
let follower = leader.next;
leader.next = newNode;
newNode.prev = leader;
newNode.next = follower;
follower.prev = newNode;
this.length++;
return this;
}
// Remove a node at a specific index
remove(index) {
if (index < 0 || index >= this.length) {
return null; // Or throw an error
}
if (index === 0) {
this.head = this.head.next;
if (this.head) { // Check if list is now empty
this.head.prev = null;
} else {
this.tail = null; // If list is empty, update tail as well
}
} else {
let leader = this.traverseToIndex(index - 1);
let unwantedNode = leader.next;
let follower = unwantedNode.next;
leader.next = follower;
if (follower) { // Check if removing the last element
follower.prev = leader;
} else {
this.tail = leader; // If removing last element, update tail
}
}
this.length--;
return this;
}
// Traverse to a specific index
traverseToIndex(index) {
let currentNode = this.head;
let count = 0;
while (count !== index) {
currentNode = currentNode.next;
count++;
}
return currentNode;
}
// Print the list (for debugging)
printList() {
let currentNode = this.head;
const arr = [];
while (currentNode !== null) {
arr.push(currentNode.data);
currentNode = currentNode.next;
}
console.log(arr);
return this;
}
}
// Example usage:
const myList = new DoublyLinkedList();
myList.append(10);
myList.append(20);
myList.prepend(5);
myList.insert(2, 15);
myList.remove(1);
myList.printList(); // Output: [5, 15, 20]
Key improvements in this version:
- Clarity and Comments: Added more comments to explain the purpose of each function and section of the code.
- Error Handling:
insert
andremove
now handle invalid index inputs more gracefully, either by returningfalse
ornull
(you could also throw an error if that's preferred in your application). - Edge Case Handling in
remove
: Theremove
method now correctly handles removing the first and last elements of the list, including