本文主要写了对于链表的操作,功能:链表添加到最后,指定位置和元素内容添加,根据位置删除,根据元素内容删除,链表长度、是否为空、获取第一个节点、获取链表字符串内容、根据元素获取位置。
class Node {
constructor(value) {
this.element = value;
this.next = null;
}
}
function defaultEquals(a, b) {
return a === b;
}
class LinkedList {
constructor(equalsFn = defaultEquals) {
this.head = undefined; // 保持第一个元素的饮用
this.count = 0; // 存储链表的元素数量
this.equalsFn = equalsFn; // 比较两个节点的元素是否相同
}
push(element) {
const node = new Node(element); // 创建一个节点
let current;
if (this.head == null) {
// undefined == null 为 true
// 此时链表上没有任何元素,只需要在第一个节点添加即可
// node 节点的next 默认是 null 所以,链表的next 也是null
this.head = node;
} else {
// 只能找到第一个节点元素的引用,因此需要从第一个节点开始循环
current = this.head;
// 找到链表中的最后一个节点
while (current.next != null) {
current = current.next;
}
current.next = node;
}
this.count++;
}
// 插入元素到指定位置
insert(element, index) {
if (index > 0 && index <= this.count) {
const node = new Node(element);
if (index === 0) {
let current = this.head;
node.next = current;
this.head = node;
} else {
const previous = this.getElementAt(index - 1);
node.next = previous.next;
previous.next = node;
}
this.count++;
return true;
}
return false;
}
// 根据输入循环链表
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;
}
// 删除特定位置的节点
removeAt(index) {
// 验证传入的节点位置是否有效
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;
// for (let i = 0; i < index; i++) {
// // 因为每次循环 都会将 current.next 的值赋给 current,所以节点循环是通过 current 进行
// previous = current; //
// current = current.next;
// }
// // 删除 index 位置上的 元素节点,只需要改变要删除节点的引用,就可以将这个节点从链表中删除。
// // previous 要删除的节点的前一个节点
// /*
// 节点位置:0 1 2 3 4
// 节点元素:1 2 3 4 5
// 删除输入的是 3
// 上面循环:
// 0 1 2
// 1 2 3
// previous 的节点内容是 3
// */
previous.next = current.next;
}
this.count--;
return current.element;
}
return undefined;
}
// 根据元素删除节点
remove(element) {
const index = this.indexOf(element);
return this.removeAt(index);
}
// 根据节点内容查找所在的位置
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.count > 0) {
let objString = '';
let current = this.head;
for (let i = 0; i < this.count && current != null; i++) {
objString = `${objString} ${i}-${current.element}`;
current = current.next;
}
return objString;
}
}
// 链表逆序
reverse() {
let current = this.head;
let prev = null;
while (current) {
const nextTemp = current.next;
current.next = prev;
prev = current;
current = nextTemp;
}
this.head = prev; // 算法题不用写这一行
return prev;
}
}