Definition
A doubly linked list is a linear data structure that represents a collection of elements, where each element points both to the next and the previous one. The first element in the doubly linked list is the head and the last element is the tail.
Each element of a doubly linked list data structure must have the following properties:
value: The value of the elementnext: A pointer to the next element in the linked list (nullif there is none)previous: A pointer to the previous element in the linked list (nullif there is none)
The main properties of a doubly linked list data structure are:
size: The number of elements in the doubly linked listhead: The first element in the doubly linked listtail: The last element in the doubly linked list
The main operations of a doubly linked list data structure are:
insertAt: Inserts an element at the specific indexremoveAt: Removes the element at the specific indexgetAt: Retrieves the element at the specific indexclear: Empties the doubly linked listreverse: Reverses the order of elements in the doubly linked list
Implementation
代码实现
class DoublyLinkedList {
constructor() {
this.nodes = [];
}
get size() {
return this.nodes.length;
}
get head() {
return this.size ? this.nodes[0] : null;
}
get tail() {
return this.size ? this.nodes[this.size - 1] : null;
}
insertAt(index, value) {
const previousNode = this.nodes[index - 1] || null;
const nextNode = this.nodes[index] || null;
const node = { value, next: nextNode, previous: previousNode };
if (previousNode) previousNode.next = node;
if (nextNode) nextNode.previous = node;
this.nodes.splice(index, 0, node);
}
insertFirst(value) {
this.insertAt(0, value);
}
insertLast(value) {
this.insertAt(this.size, value);
}
getAt(index) {
return this.nodes[index];
}
removeAt(index) {
const previousNode = this.nodes[index - 1] || null;
const nextNode = this.nodes[index + 1] || null;
if (previousNode) previousNode.next = nextNode;
if (nextNode) nextNode.previous = previousNode;
return this.nodes.splice(index, 1);
}
clear() {
this.nodes = [];
}
reverse() {
this.nodes = this.nodes.reduce((acc, { value }) => {
const nextNode = acc[0] || null;
const node = { value, next: nextNode, previous: null };
if (nextNode) nextNode.previous = node;
return [node, ...acc];
}, []);
}
*[Symbol.iterator]() {
yield* this.nodes;
}
}
- Create a
classwith aconstructorthat initializes an empty array,nodes, for each instance. - Define a
sizegetter, that returns that usesArray.prototype.lengthto return the number of elements in thenodesarray. - Define a
headgetter, that returns the first element of thenodesarray ornullif empty. - Define a
tailgetter, that returns the last element of thenodesarray ornullif empty. - Define an
insertAt()method, which usesArray.prototype.splice()to add a new object in thenodesarray, updating thenextandpreviouskeys of the previous and next elements respectively. - Define two convenience methods,
insertFirst()andinsertLast()that use theinsertAt()method to insert a new element at the start or end of thenodesarray respectively. - Define a
getAt()method, which retrieves the element in the givenindex. - Define a
removeAt()method, which usesArray.prototype.splice()to remove an object in thenodesarray, updating thenextandpreviouskeys of the previous and next elements respectively. - Define a
clear()method, which empties thenodesarray. - Define a
reverse()method, which usesArray.prototype.reduce()and the spread operator (...) to reverse the order of thenodesarray, updating thenextandpreviouskeys of each element appropriately. - Define a generator method for
Symbol.iterator, which delegates to thenodesarray’s iterator using theyield*syntax.
使用样例
const list = new DoublyLinkedList();
list.insertFirst(1);
list.insertFirst(2);
list.insertFirst(3);
list.insertLast(4);
list.insertAt(3, 5);
list.size; // 5
list.head.value; // 3
list.head.next.value; // 2
list.tail.value; // 4
list.tail.previous.value; // 5
[...list.map(e => e.value)]; // [3, 2, 1, 5, 4]
list.removeAt(1); // 2
list.getAt(1).value; // 1
list.head.next.value; // 1
[...list.map(e => e.value)]; // [3, 1, 5, 4]
list.reverse();
[...list.map(e => e.value)]; // [4, 5, 1, 3]
list.clear();
list.size; // 0
翻译自:https://www.30secondsofcode.org/js/s/data-structures-doubly-linked-list