一、定义
链表存储有序的元素集合,但不同于数组,链表中的元素并不是连续放置的。每个项有一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或连接组成)。
二、JavaScript模拟实现
// 工具类
function defualtEquals(a, b) {
return a === b;
}
// 链表的每一项
class Node {
constructor(ele) {
this.element = ele;
this.next = null;
}
}
// 链表
class LinkedList {
constructor(equalsFn = defualtEquals) { // 默认值defualEquals
this.count = 0;
this.head = null; // 头指针
this.equalsFn = equalsFn;
}
// 末尾添加元素
push(element) {
const node = new Node(element);
let current;
if (this.head === null) {
this.head = node;
} else {
current = this.head;
while (current.next !== null) {
current = current.netx;
}
current.next = node;
}
this.count++;
}
// 移除指定位置元素
removeAt(index) {
// 判断是否越界
if (index >= 0 && index <= this.count) {
let current = this.head;
if (index === 0) {
this.head = current.next;
} else {
let previous;
for (let i = 0; i < index; i++) {
previous = current;
current = current.next;
}
// const previous = this.getElementAt(index - 1);
// current = current.next;
previous.next = current.next;
}
this.count--;
return current.ele;
}
}
// 获取链表指定位置的项
getElementAt(index) {
if (index >= 0 && index <= this.count) {
let node = this.head;
for (let i = 0; i < index; i++) {
node = node.next;
}
return node;
}
return null;
}
// 指定位置插入
insert(element, index) {
if (index >= 0 && index <= this.count) {
if (index === 0) {
const tempItem = this.head;
this.head = new Node(element);
this.head.next = tempItem;
this.count++;
return true;
} else {
let temp, previous = this.head;
for (var i = 0; i < index - 1; i++) { // 获取插入位置前一个元素
previous = previous.next;
}
temp = previous.next; // 暂存后续链表
previous.next = new Node(element);
previous.next.next = temp; // 连接
this.count++;
return true;
}
}
return false;
}
// 查找元素:返回这个元素的位置
indexOf(element) {
let current = this.head;
for (var i = 0; i < this.count; i++) {
if (this.equalsFn(current.element, element)) {
return i;
}
current = current.next;
}
return -1;
}
// 移除某个元素
remove(element) {
const index = this.indexOf(element);
return this.removeAt(index);
}
// 是否为空
isEmpty() {
return this.head === null;
}
// 求链表长度
size() {
return this.count;
}
// 获取链表的头
getHead() {
return this.head;
}
toString() {
if (this.head === null) {
return ''
}
let current = this.head.next,
str = `${this.head.element}`;
for (var i = 1; i < this.count && current !== null; i++) {
str = `${str},${current.element}`;
current = current.next
}
return str;
}
}