JavaScript 数据结构 - 链表
[定义]
链表是一种线性数据结构,它表示元素的集合,其中每个元素都指向下一个元素。链表中的第一个元素是 head,最后一个元素是 tail。
链表数据结构的每个元素必须具有以下属性:
value:元素的值next:指向链表中下一个元素的指针(如果没有)null
链表数据结构的主要属性是:
size:链表中的元素数head:链表中的第一个元素tail:链表中的最后一个元素
链表数据结构的主要操作是:
insertAt:在特定索引处插入元素removeAt:删除特定索引处的元素getAt:检索特定索引处的元素clear:清空链表reverse:反转链表中元素的顺序
[实现]
class LinkedList {
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 };
if (previousNode) previousNode.next = 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];
const nextNode = this.nodes[index + 1] || null;
if (previousNode) previousNode.next = nextNode;
return this.nodes.splice(index, 1);
}
clear() {
this.nodes = [];
}
reverse() {
this.nodes = this.nodes.reduce(
(acc, { value }) => [{ value, next: acc[0] || null }, ...acc],
[]
);
}
*[Symbol.iterator]() {
yield* this.nodes;
}
}
- 创建一个 with a 为每个实例初始化一个空数组 。
class``constructor``nodes - 定义一个 getter,它返回使用
sizeArray.prototype.length返回数组中的元素数。nodes - 定义一个 getter,它返回数组的第一个元素,或者如果为空。
head``nodes``null - 定义一个 getter,它返回数组的最后一个元素,或者如果为空。
tail``nodes``null - 定义一个方法,该方法使用
insertAt()Array.prototype.splice()在数组中添加新对象,更新前一个元素的键。nodes``next - 定义两个便捷的方法,分别使用该方法在数组的开头或结尾插入新元素。
insertFirst()``insertLast()``insertAt()``nodes - 定义一个方法,该方法检索给定 .
getAt()``index - 定义一个方法,该方法使用
removeAt()Array.prototype.splice()要删除数组中的对象,请更新前一个元素的键。nodes``next - 定义一个清空数组的方法。
clear()``nodes - 定义一个方法,该方法使用
reverse()Array.prototype.reduce()和展开运算符 (...) 反转数组的顺序,并相应地更新每个元素的键。nodes``next - 定义 的生成器方法
Symbol.iterator,它使用nodesyield*语法。
const list = new LinkedList();
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.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