JavaScript中的链表和其他数据结构中的一样,主要分成三大类:普通链表,双向链表和循环链表
普通链表
function defaultEquals(a, b) {
return a === b;
}
class Node {
constructor(element) {
this.element = element;
this.next = undefined;
}
}
class LinkedList {
constructor(equalsFn = defaultEquals) {
this.count = 0;
this.head = undefined;
this.equalsFn = equalsFn;
}
push(element) {
//向尾部添加元素:找到尾部,让其next指向node
const node = new Node(element);
let current;
if (this.head == null) {
this.head = node;
} else {
current = this.head;
while (current.next != null) {
current = current.next;
}
current.next = node;
}
this.count++;
}
removeAt(index) {
//若为head则替换掉head,若为中间则记录previous找到中间并把previous.node指向其后面
if (index >= 0 && index < this.count) {
let current = this.head;
if (index === 0) {
this.head = current.next;
} else {
const previous = this.getElementAt(index - 1);
current = previous.next;
previous.next = current.next;
}
this.count--;
return current.element;
}
return undefined;
}
remove(element) {
const index = this.indexOf(element);
return this.removeAt(index);
}
getElementAt(index) {
if (index >= 0 && index <= this.count) {
let node = this.head;
for (let i = 0; i < index && node != null; i++) {
node = node.next;
}
return node;
}
return undefined;
}
insert(element, index) {//开头、中间
if (index >= 0 && index <= this.count) {
const node = new Node(element);
if (index === 0) {
const current = this.head;
node.next = current;
this.head = node;
} else {
const previous = this.getElementAt(index - 1);
const current = previous.next;
node.next = current;
previous.next = node;
}
this.count++;//别忘了
return true;
}
return false;
}
indexOf(element) {
let current = this.head;
for (let i = 0; i < this.count && current != null; i++) {
if (this.equalsFn(element, current.element)) {
return i;
}
current = current.next;
}
return -1;
}
size() {
return this.count;
}
isEmpty() {
return this.size() === 0;
}
getHead() {
return this.head;
}
toString() {
if (this.head == null) {
return "";
}
let objString = `${this.head.element}`;
let current = this.head.next;
for (let i = 1; i < this.size() && current != null; i++) {
objString = `${objString},${current.element}`;
current = current.next;
}
return objString;
}
}
双向链表
//双向链表,每个节点有前后两个指针
//head.prev=undefined tail.next=undefined
class DoublyNode extends Node {
constructor(element, next, prev) {
super(element, next);
this.prev = prev; // 新增的
}
}
class DoublyLinkedList extends LinkedList {
constructor(equalsFn = defaultEquals) {
super(equalsFn); // 继承LinkedList
this.tail = undefined; //指向末尾的元素
}
insert(element, index) {
//插在开头(为空/不为空),插在结尾,插在中间
if (index >= 0 && index <= this.count) {
const node = new DoublyNode(element);
let current = this.head;
if (index === 0) {
if (this.head == null) {
// 新增的
this.head = node;
this.tail = node;
} else {
node.next = this.head;
current.prev = node; //新增的
this.head = node;
}
} else if (index === this.count) {
// 最后一项
current = this.tail;
current.next = node;
node.prev = current;
this.tail = node;
} else {
const previous = this.getElementAt(index - 1);
current = previous.next;
node.next = current;
previous.next = node;
current.prev = node; // 新增的
node.prev = previous; // 新增的
}
this.count++;
return true;
}
return false;
}
removeAt(index) {
//移除开头(只有一个or not),移除末尾(注意tail的设置),移除中间
if (index >= 0 && index < this.count) {
let current = this.head;
if (index === 0) {
this.head = current.next;
// 如果只有一项,更新tail // 新增的
if (this.count === 1) {
this.tail = undefined;
} else {
this.head.prev = undefined;
}
} else if (index === this.count - 1) {
// 最后一项 //新增的
current = this.tail;
this.tail = current.prev;
this.tail.next = undefined;
} else {
current = this.getElementAt(index);
const previous = current.prev;
// 将previous与current的下一项链接起来——跳过current
previous.next = current.next;
current.next.prev = previous; // 新增的
}
this.count--;
return current.element;
}
return undefined;
}
}
循环链表
//循环链表
//head.prev=tail,尾部节点.next=head
class CircularLinkedList extends LinkedList {
constructor(equalsFn = defaultEquals) {
super(equalsFn);
}
insert(element, index) {
//插在开头时,要注意更新最后一个元素的next
if (index >= 0 && index <= this.count) {
const node = new Node(element);
let current = this.head;
if (index === 0) {
if (this.head == null) {
this.head = node;
node.next = this.head; //新增的
} else {
node.next = current;
current = this.getElementAt(this.size());
// 更新最后一个元素
this.head = node;
current.next = this.head; //新增的
}
} else {
// 这种场景没有变化
const previous = this.getElementAt(index - 1);
node.next = previous.next;
previous.next = node;
}
this.count++;
return true;
}
return false;
}
removeAt(index) {
//注意删除首元素时末尾元素的next
if (index >= 0 && index < this.count) {
let current = this.head;
if (index === 0) {
if (this.size() === 1) {
this.head = undefined;
} else {
const removed = this.head;
current = this.getElementAt(this.size()); // 新增的
this.head = this.head.next;
current.next = this.head;
current = removed;
}
} else {
// 不需要修改循环链表最后一个元素
const previous = this.getElementAt(index - 1);
current = previous.next;
previous.next = current.next;
}
this.count--;
return current.element;
}
return undefined;
}
}