# Two way linked list: I’m no longer driving in one direction

Time：2021-8-12

Unlike a single linked list, each node of a two-way linked list contains not only data, but also pointers to its front node and rear node respectively In fact, compared with a single linked list, a double linked list adds a pointer to the previous node

Let me write a double linked list to implement some methods:

<img style=”zoom:80%;” />

We first implement a node constructor:

``````class Node {
constructor(element) {
this.element = element;  //  Node data value
this.next = null;  //  Front pointer
this.prev = null;  //  Rear pointer
}
}``````

## Overall structure of bidirectional linked list

``````class DoubleLinkedList {
constructor() {
this.count = 0; //  Number of record nodes
this.tail = null; //  Bidirectional linked list tail
}

//Remove the node at the specified position in the linked list
removeAt(index) {}

//Remove the specified node of the linked list
remove(element) {}

reverse() {}

//Swap the location of two nodes
swap() {}

traverse() {}

//Find the index of a node
find() {}

//Query whether the linked list is empty
isEmpty() {}

length() {}
}``````

The next step is to implement this one by one

Find the node according to the location (index). The next method will always use this method. Simply encapsulate it into a method for calling

``````getElement(index) {
if (index >= 0 && index < this.count) {
//Loop through to the node
for (let i = 0; i < index; i++) {
node = node.next;
}
return node;
}
return undefined;
}``````

<img style=”zoom:80%;” />

### 1.1 add nodes at the tail

``````//Pass in a node
//Create a node first
const node = new Node(element);
//If the linked list is empty, both the head node and the tail node are nodes
if (this.head === null && this.tail === null) {
this.tail = node
}
else {
node.prev = this.tail;
this.tail.next = node;
this.tail = node;
}
//Total number of nodes + 1
this.count++;
}``````

### 1.2 add a node at the specified position in the linked list

``````addAt(index, element) {
if (index >= 0 && index <= this.count) {
const node = new Node(element);
if (index === 0) {
}
//Insert node at tail
else if (index === this.count) {
this.count--;
}
//Insert node in the middle
else {
let current = this.getElement(index);
//First, set the relationship between the new node and the previous node
node.prev = current.prev;
current.prev.next = node;
//Then set the relationship between the new node and the next node
node.next = current;
current.prev = node
}
this.count++;
return true
}
return false;
}``````

## 2. Remove node

<img style=”zoom:80%;” />

### 2.1. Remove the node at the specified position of the linked list

``````removeAt(index) {
if (index >= 0 && index < this.count) {
if (index === 0) {
}
//Remove tail node
else if (index === this.count - 1) {
this.tail = this.tail.prev;
this.tail.next = null;
}
//Remove intermediate node
else {
let current = this.getElement(index);
current.next.prev = current.prev
current.prev.next = current.next
}
this.count--;
return true
}
return undefined;
}``````

### 2.2. Remove the specified node of the linked list

To remove a specified node, you must first find it

``````remove(element) {
while (current) {
if (current === element) {
//The linked list has only one node
if (current === this.head && current === this.prev) {
this.tail = null;
}
else if (current === this.head) {
}
//Remove tail node
else if (current === this.tail) {
this.tail = this.tail.prev;
this.tail.next = null;
}
//Remove intermediate node
else {
current.next.prev = current.prev;
current.prev.next = current.next;
}
this.count--;
}
current = current.next;
}
}``````

``````reverse() {
let prev = null;
//Put the middle first
while (current) {
let next = current.next;

//Back and forth inversion
current.next = prev;
current.prev = next;

prev = current;
current = next
}
}``````

## 6. Swap the location of two nodes

``````swap(index1, index2) {
if (index1 >= 0 && index1 < this.count && index2 >= 0 && index2 < this.count) {
let node1 = this.getElement(index1)
let node2 = this.getElement(index2)
//Let index1 always be less than index2 to facilitate subsequent search and exchange
if (index1 > index2) {
return this.swap(index2, index1)
}
//Swap the values of two nodes
[node1.element, node2.element] = [node2.element, node1.element]
return true
}
return undefined;
}``````

``````display() {
if (!this.isEmpty()) {
let result = '';
while (current) {
result += current.element
current = current.next
if (current) {
result += '->';
}
}
return result;
}
return undefined;
}``````

## 8. Find the index of a node

``````find(element) {
let index = 0
while (current) {
if (current === element) {
return index;
}
current = current.next;
index++;
}
return undefined
}``````

## 9. Query whether the linked list is empty

``````isEmpty() {
return this.count === 0
}``````

## 10. Length of query linked list

``````length() {
return this.count;
}``````

Consolidate:

``````//Implement a node constructor
class Node {
constructor(element) {
this.element = element;
this.next = null;
this.prev = null;
}
}

constructor() {
this.count = 0; //  Number of record nodes
this.tail = null; //Bidirectional linked list尾部
}

//Traverse a method and loop to the target location
getElement(index) {
if (index >= 0 && index < this.count) {
for (let i = 0; i < index; i++) {
node = node.next;
}
return node;
}
return undefined;
}

//Create a node first
const node = new Node(element);
//If the linked list is empty
if (this.head === null && this.tail === null) {
this.tail = node
}
else {
node.prev = this.tail;
this.tail.next = node;
this.tail = node;
}
this.count++;
}

if (index >= 0 && index <= this.count) {
const node = new Node(element);
if (index === 0) {
} else if (index === this.count) {
this.count--;
}
else {
let current = this.getElement(index);
//First, set the relationship between the new node and the previous node
node.prev = current.prev;
current.prev.next = node;
//Then set the relationship between the new node and the next node
node.next = current;
current.prev = node
}
this.count++;
return true
}
return false;
}

//Remove the node at the specified position in the linked list
removeAt(index) {
if (index >= 0 && index < this.count) {
if (index === 0) {
}
//Remove tail node
else if (index === this.count - 1) {
this.tail = this.tail.prev;
this.tail.next = null;
}
//Remove intermediate node
else {
let current = this.getElement(index);
current.next.prev = current.prev
current.prev.next = current.next
}
this.count--;
return true
}
return undefined;
}

//Remove the specified node of the linked list
remove(element) {
while (current) {
if (current === element) {
//The linked list has only one node
if (current === this.head && current === this.prev) {
this.tail = null;
}
else if (current === this.head) {
}
//Remove tail node
else if (current === this.tail) {
this.tail = this.tail.prev;
this.tail.next = null;
}
//Remove intermediate node
else {
current.next.prev = current.prev;
current.prev.next = current.next;
}
this.count--;
}
current = current.next;
}
}

reverse() {
let prev = null;

while (current) {
let next = current.next;

//Back and forth inversion
current.next = prev;
current.prev = next;

prev = current;
current = next
}
}

//Swap the location of two nodes
swap(index1, index2) {
if (index1 >= 0 && index1 < this.count && index2 >= 0 && index2 < this.count) {
let node1 = this.getElement(index1)
let node2 = this.getElement(index2)
//Let index1 always be less than index2 to facilitate subsequent search and exchange
if (index1 > index2) {
return this.swap(index2, index1)
}
//Swap the values of two nodes
[node1.element, node2.element] = [node2.element, node1.element]
return true
}
return undefined;
}

display() {
if (!this.isEmpty()) {
let result = '';
while (current) {
result += current.element
current = current.next
if (current) {
result += '->';
}
}
return result;
}
return undefined;
}

//Find the index of a node
find(element) {
let index = 0
while (current) {
if (current === element) {
return index;
}
current = current.next;
index++;
}
return undefined
}

//Query whether the linked list is empty
isEmpty() {
return this.count === 0
}

length() {
return this.count;
}
}``````

Let’s call:

``````//First instantiate a two-way linked list object

//Traversal
console.log(DLL.display()); // 3->1->2->6
//Delete by location
DLL.removeAt(3);

//Swap two nodes
DLL.swap(0, 2)
console.log(DLL.display()); // 2->1->3
//Flip
DLL.reverse();
console.log(DLL.isEmpty()); // false