Introduction
A Doubly Linked List is a linear data structure where each node has a reference to both the next and previous node. This allows traversal in both directions, forward and backward, compared to a singly linked list where traversal is only possible in one direction. Each node in a doubly linked list contains:
- Data: The value stored in the node.
- Next Pointer: A reference to the next node in the list.
- Previous Pointer: A reference to the previous node in the list.
This guide will walk you through writing a JavaScript program to implement a doubly linked list with basic operations such as insertion, deletion, and traversal.
Problem Statement
Create a JavaScript program that:
- Implements a Doubly Linked List.
- Supports operations such as:
- Insertion: Insert a node at the head, tail, or at a specific position.
- Deletion: Remove a node from the head, tail, or at a specific position.
- Traversal: Traverse the list forward and backward to display the elements.
Example:
- Input: Insert values
10, 20, 30, 40
- Output (forward):
10 <-> 20 <-> 30 <-> 40
Solution Steps
- Define a Node Class: Create a class that stores the data, the next node, and the previous node.
- Define the Doubly Linked List Class: Implement methods for:
- Insertion at the head, tail, or specific position.
- Deletion from the head, tail, or specific position.
- Traversal in both directions.
- Display the List: Traverse the list and print the nodes.
JavaScript Program
Step 1: Define the Node Class
// JavaScript Program to Implement a Doubly Linked List
// Author: https://www.rameshfadatare.com/
class Node {
constructor(data) {
this.data = data; // Data part of the node
this.next = null; // Pointer to the next node
this.prev = null; // Pointer to the previous node
}
}
Step 2: Define the Doubly Linked List Class
class DoublyLinkedList {
constructor() {
this.head = null; // Head of the list
this.tail = null; // Tail of the list
}
// Insert at the end (tail) of the doubly linked list
insertAtEnd(data) {
const newNode = new Node(data);
if (this.head === null) {
// If the list is empty, set both head and tail to the new node
this.head = this.tail = newNode;
} else {
// Otherwise, append the new node at the end and update the tail
newNode.prev = this.tail;
this.tail.next = newNode;
this.tail = newNode;
}
console.log(`${data} inserted at the end`);
}
// Insert at the beginning (head) of the doubly linked list
insertAtBeginning(data) {
const newNode = new Node(data);
if (this.head === null) {
// If the list is empty, set both head and tail to the new node
this.head = this.tail = newNode;
} else {
// Insert the new node before the current head
newNode.next = this.head;
this.head.prev = newNode;
this.head = newNode;
}
console.log(`${data} inserted at the beginning`);
}
// Delete a node from the end of the list
deleteFromEnd() {
if (this.tail === null) {
console.log("List is empty");
return;
}
console.log(`${this.tail.data} deleted from the end`);
if (this.head === this.tail) {
// If there's only one element, set both head and tail to null
this.head = this.tail = null;
} else {
// Update the tail to the previous node
this.tail = this.tail.prev;
this.tail.next = null;
}
}
// Delete a node from the beginning of the list
deleteFromBeginning() {
if (this.head === null) {
console.log("List is empty");
return;
}
console.log(`${this.head.data} deleted from the beginning`);
if (this.head === this.tail) {
// If there's only one element, set both head and tail to null
this.head = this.tail = null;
} else {
// Update the head to the next node
this.head = this.head.next;
this.head.prev = null;
}
}
// Traverse the list forward (from head to tail)
traverseForward() {
if (this.head === null) {
console.log("List is empty");
return;
}
let current = this.head;
let result = "";
console.log("List (Forward):");
while (current !== null) {
result += current.data + (current.next ? " <-> " : "");
current = current.next;
}
console.log(result);
}
// Traverse the list backward (from tail to head)
traverseBackward() {
if (this.tail === null) {
console.log("List is empty");
return;
}
let current = this.tail;
let result = "";
console.log("List (Backward):");
while (current !== null) {
result += current.data + (current.prev ? " <-> " : "");
current = current.prev;
}
console.log(result);
}
}
Step 3: Example Usage
// Example usage of the Doubly Linked List
const dll = new DoublyLinkedList();
// Insertion at the end
dll.insertAtEnd(10);
dll.insertAtEnd(20);
dll.insertAtEnd(30);
dll.insertAtEnd(40);
// Traverse forward
dll.traverseForward(); // Output: 10 <-> 20 <-> 30 <-> 40
// Insertion at the beginning
dll.insertAtBeginning(5);
// Traverse forward and backward
dll.traverseForward(); // Output: 5 <-> 10 <-> 20 <-> 30 <-> 40
dll.traverseBackward(); // Output: 40 <-> 30 <-> 20 <-> 10 <-> 5
// Deletion from the beginning and end
dll.deleteFromBeginning(); // Output: 5 deleted from the beginning
dll.deleteFromEnd(); // Output: 40 deleted from the end
// Traverse forward again
dll.traverseForward(); // Output: 10 <-> 20 <-> 30
Output Example
10 inserted at the end
20 inserted at the end
30 inserted at the end
40 inserted at the end
List (Forward):
10 <-> 20 <-> 30 <-> 40
5 inserted at the beginning
List (Forward):
5 <-> 10 <-> 20 <-> 30 <-> 40
List (Backward):
40 <-> 30 <-> 20 <-> 10 <-> 5
5 deleted from the beginning
40 deleted from the end
List (Forward):
10 <-> 20 <-> 30
Explanation
Step 1: Define the Node Class
- The
Node
class represents each node in the doubly linked list. Each node has:data
: The value stored in the node.next
: A reference to the next node in the list.prev
: A reference to the previous node in the list.
Step 2: Define the Doubly Linked List Class
- Insert at End: The
insertAtEnd()
method inserts a node at the tail of the list. - Insert at Beginning: The
insertAtBeginning()
method inserts a node at the head of the list. - Delete from End: The
deleteFromEnd()
method removes the node from the tail of the list. - Delete from Beginning: The
deleteFromBeginning()
method removes the node from the head of the list. - Traverse Forward: The
traverseForward()
method traverses the list from the head to the tail and prints the nodes. - Traverse Backward: The
traverseBackward()
method traverses the list from the tail to the head and prints the nodes.
Step 3: Example Usage
- The doubly linked list is created, and various operations such as insertion, deletion, and traversal are performed.
Conclusion
This JavaScript program implements a doubly linked list with basic operations like insertion, deletion, and traversal. Doubly linked lists are useful when you need to efficiently traverse or modify a list in both directions, making them a versatile data structure for various applications.
Comments
Post a Comment
Leave Comment