返回
链表类在JavaScript的演变:从零到通透
前端
2024-02-22 03:26:33
从零开始,用JavaScript构建链表类
在JavaScript中,没有栈、队列、链表等明显的结构,但我们可以利用对象伪造这些结构。这次,我们将用对象构建链表相关类:单向链表、有序链表、循环链表和双向链表。
1. 单向链表
单向链表是最基本也是最常见的链表。它由一系列节点组成,每个节点包含一个值和指向下一个节点的指针。
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
append(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
this.tail = newNode;
}
this.length++;
}
prepend(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
} else {
newNode.next = this.head;
this.head = newNode;
}
this.length++;
}
insert(value, index) {
if (index === 0) {
this.prepend(value);
} else if (index >= this.length) {
this.append(value);
} else {
const newNode = new Node(value);
let current = this.head;
for (let i = 0; i < index - 1; i++) {
current = current.next;
}
newNode.next = current.next;
current.next = newNode;
this.length++;
}
}
remove(index) {
if (index === 0) {
this.head = this.head.next;
if (this.head === null) {
this.tail = null;
}
} else if (index >= this.length - 1) {
let current = this.head;
while (current.next !== this.tail) {
current = current.next;
}
current.next = null;
this.tail = current;
} else {
let current = this.head;
for (let i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
this.length--;
}
this.length--;
}
get(index) {
if (index >= this.length) {
return undefined;
}
let current = this.head;
for (let i = 0; i < index; i++) {
current = current.next;
}
return current.value;
}
set(value, index) {
if (index >= this.length) {
return undefined;
}
let current = this.head;
for (let i = 0; i < index; i++) {
current = current.next;
}
current.value = value;
}
print() {
let current = this.head;
while (current) {
console.log(current.value);
current = current.next;
}
}
}
const list = new LinkedList();
list.append(1);
list.append(2);
list.append(3);
list.prepend(0);
list.insert(4, 2);
list.remove(2);
list.set(5, 2);
list.get(2);
list.print();
2. 有序链表
有序链表是一种特殊的单向链表,其节点按值升序排列。
class SortedLinkedList extends LinkedList {
constructor() {
super();
}
append(value) {
if (this.head === null) {
this.head = new Node(value);
this.tail = this.head;
} else {
let current = this.head;
while (current.next !== null && value > current.value) {
current = current.next;
}
if (value <= current.value) {
const newNode = new Node(value);
newNode.next = current;
if (current === this.head) {
this.head = newNode;
} else {
let previous = this.head;
while (previous.next !== current) {
previous = previous.next;
}
previous.next = newNode;
}
} else {
const newNode = new Node(value);
newNode.next = current.next;
current.next = newNode;
if (newNode.next === null) {
this.tail = newNode;
}
}
}
this.length++;
}
insert(value, index) {
if (index === 0) {
this.prepend(value);
} else if (index >= this.length) {
this.append(value);
} else {
let current = this.head;
for (let i = 0; i < index - 1; i++) {
current = current.next;
}
const newNode = new Node(value);
newNode.next = current.next;
current.next = newNode;
this.length++;
}
}
}
const sortedList = new SortedLinkedList();
sortedList.append(1);
sortedList.append(2);
sortedList.append(3);
sortedList.prepend(0);
sortedList.insert(4, 2);
sortedList.remove(2);
sortedList.set(5, 2);
sortedList.get(2);
sortedList.print();
3. 循环链表
循环链表是一种特殊的单向链表,其最后一个节点指向第一个节点,形成一个环。
class CircularLinkedList extends LinkedList {
constructor() {
super();
}
append(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
newNode.next = this.head;
} else {
this.tail.next = newNode;
this.tail = newNode;
newNode.next = this.head;
}
this.length++;
}
prepend(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
newNode.next = this.head;
} else {
newNode.next = this.head;
this.head = newNode;
this.tail.next = this.head;
}
this.length++;
}
}
const circularList = new CircularLinkedList();
circularList.append(1);
circularList.append(2);
circularList.append(3);
circularList.prepend(0);
circularList.remove(2);
circularList.set(5, 2);
circularList.get(2);
circularList.print();
4. 双向链表
双向链表是一种特殊的链表,其节点除了指向下一个节点外,还指向上一个节点。
class DoublyLinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
append(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
newNode.prev = this.tail;
this.tail = newNode;
}
this.length++;
}
prepend(value) {
const newNode = new Node(value);
if (