在 JavaScript 中,我们使用数组来进行有序序列的数据存放,方便省事,而且在 JavaScript 中我们不需要担心数组大小不够扩容问题,并且找某个位置上的数据的复杂度为 O(1),但是在任意位置上删除和添加的平均时间复杂度为 O(n),我们使用链表的删除和增加时间复杂度是为 O(1) 的,所以我们来实现一个单链表。
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class SingleList {
// 构造函数
constructor() {
this.head = new Node('head');
this.size = 0;
this.currNode = '';
}
// 找到指定的元素
findElement(item) {
let head = this.head;
while ( head && head.data !== item ) {
head = head.next;
}
return head;
}
// 找到最后一个元素
findLastElement() {
let head = this.head;
while (head && head.next !== null) {
head = head.next;
}
return head;
}
// 末尾添加一个元素
pushElement(value) {
let newNode = new Node(value);
let lastElement = this.findLastElement();
lastElement.next = newNode;
this.size++;
}
// 在任意位置添加一个节点
insertElement(item, element) {
let selectElement = this.findElement(item);
if(!selectElement) return;
let newNode = new Node(element);
newNode.next = selectElement.next;
selectElement.next = newNode;
this.size++;
}
// 末尾删除一个元素
removeLastElement() {
let lastElement = this.findLastElement();
let head = this.head;
while (head.next.data !== lastElement.data) {
head = head.next;
}
head.next = null;
this.size--;
}
// 删除节点
removeElement(item) {
if (!this.findElement(item)) return '元素不存在';
if (item === 'head') {
if (!(this.isEmpty())) {
return;
} else {
this.head.next = null;
return;
}
}
let currNode = this.head;
while (currNode.next.data !== item) {
if (!currNode.next) {
return '元素下一个节点不存在';
}
currNode = currNode.next;
}
currNode.next = currNode.next.next;
this.size--;
}
// 判断单链表是否为空
isEmpty() {
return this.size === 0;
}
// 单链表的遍历
print() {
let result = '';
let head = this.head;
while ( head ) {
result += head.data;
head = head.next;
if (head) {
result += '->';
}
}
console.log(result);
}
// 显示当前节点
show() {
console.log(this.currNode.data || 'head');
}
// 获取单链表的长度
getLength() {
return this.size;
}
// 清空
clear() {
this.head.next = null;
this.size = 0;
}
// 当前节点向后移动元素到第n个
advance(n, currNode = this.head) {
this.currNode = (typeof currNode !== 'object') ? this.findElement(currNode) : currNode;
while((n--) && this.currNode.next) {
this.currNode = this.currNode.next;
}
return this.currNode;
}
}
let myList = new SingleList();
myList.pushElement('a');
myList.pushElement('b');
myList.pushElement('c');
myList; // {data: 'head', next: {data: 'a', next: {...}}}
myList.findElement('b'); // {data: 'b', next: {}}
myList.findLastElement(); // {data: 'c', next: null};
myList.insertElement('b', 'd'); // {data: 'b', next: {data: 'd', next: {...}}}
myList.removeElement('d'); // {data: 'b', next: {data: 'c', next: {...}}}
myList.removeLastElement(); // {data: 'b', next: null};
myList.isEmpty(); // false;
myList.print; // head->a->b
myList.show(); // head
myList.getLength(); // 2
myList.clear(); // {data: 'head', next: null};
myList.advance(2); // currNode: {data: 'b', next: null};