📅  最后修改于: 2023-12-03 15:11:14.736000             🧑  作者: Mango
LinkedList,也称为链表,是一种常用的数据结构。它由一系列节点组成,每个节点包含数据和指向下一个节点的地址。相比于Array,LinkedList在插入和删除元素时更加高效,但是访问元素时则需要遍历整个链表。
我们可以用Javascript来实现LinkedList。首先,我们需要定义一个Node类来表示每个节点:
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
每个Node对象包含一个value属性和一个next属性,分别表示节点的值和下一个节点的地址。
接下来,我们定义一个LinkedList类来管理整个链表:
class LinkedList {
constructor() {
this.head = null;
this.tail = null;
this.length = 0;
}
}
LinkedList类有三个属性:head表示链表的头节点,tail表示链表的尾节点,length表示链表的长度。
我们可以实现以下几个方法来操作LinkedList:
append方法用于在链表的末尾添加一个节点。具体实现如下:
append(value) {
const node = new Node(value);
if (!this.head) {
this.head = node;
this.tail = node;
} else {
this.tail.next = node;
this.tail = node;
}
this.length++;
}
append方法首先创建一个新的Node对象,然后判断链表是否为空。如果链表为空,将head和tail都指向新创建的节点。否则,将tail节点的next属性指向新创建的节点,并将tail指向新创建的节点。最后,链表长度加1。
insert方法用于在链表的任意位置插入一个节点。具体实现如下:
insert(index, value) {
if (index < 0 || index > this.length) {
throw new Error('Index out of range');
}
const node = new Node(value);
if (index === 0) {
node.next = this.head;
this.head = node;
if (!this.tail) {
this.tail = node;
}
} else if (index === this.length) {
this.tail.next = node;
this.tail = node;
} else {
let i = 0;
let prev = null;
let current = this.head;
while (i < index) {
prev = current;
current = current.next;
i++;
}
prev.next = node;
node.next = current;
}
this.length++;
}
insert方法首先判断index是否合法,即是否在链表范围内。然后创建一个新的Node对象。如果index为0,即在链表头插入节点,将新创建的节点的next属性指向head节点,然后将head指向新创建的节点。如果链表为空,同时也将tail指向新创建的节点。如果index等于链表长度,即在链表末尾插入节点,将tail节点的next属性指向新创建的节点,并将tail指向新创建的节点。否则,遍历链表找到index位置的节点,将新创建的节点插入到前一个节点prev和后一个节点current之间。最后,链表长度加1。
remove方法用于删除链表中某个节点。具体实现如下:
remove(index) {
if (index < 0 || index >= this.length) {
throw new Error('Index out of range');
}
let deletedNode = null;
if (index === 0) {
deletedNode = this.head;
this.head = this.head.next;
if (this.length === 1) {
this.tail = null;
}
} else if (index === this.length - 1) {
let current = this.head;
let prev = null;
while (current !== this.tail) {
prev = current;
current = current.next;
}
deletedNode = current;
prev.next = null;
this.tail = prev;
} else {
let i = 0;
let prev = null;
let current = this.head;
while (i < index) {
prev = current;
current = current.next;
i++;
}
deletedNode = current;
prev.next = current.next;
}
this.length--;
return deletedNode.value;
}
remove方法首先判断index是否合法,同样是在链表范围内。然后遍历链表找到index位置的节点。如果index为0,即要删除链表头节点,将head指向head节点的next属性,并将被删除的节点返回。如果链表长度为1,同样将tail指向null。如果index为链表长度减1,即要删除链表尾节点,需要遍历链表找到尾节点前一个节点prev,将prev的next属性指向null,并将tail指向prev节点。如果index为中间节点,那么需要遍历链表找到被删除节点的前一个节点prev和后一个节点current,将prev的next属性指向current的next属性,再将被删除的节点返回。最后,链表长度减1。
get方法用于查找链表中某个节点的值。具体实现如下:
get(index) {
if (index < 0 || index >= this.length) {
throw new Error('Index out of range');
}
let i = 0;
let current = this.head;
while (i < index) {
current = current.next;
i++;
}
return current.value;
}
get方法同样判断index是否合法。然后遍历链表找到index位置的节点,并返回节点的value属性。
indexOf方法用于查找链表中某个节点的位置。具体实现如下:
indexOf(value) {
let i = 0;
let current = this.head;
while (current) {
if (current.value === value) {
return i;
}
current = current.next;
i++;
}
return -1;
}
indexOf方法遍历整个链表查找值为value的节点。如果找到了,返回节点的位置。否则,返回-1。
我们来看一个简单的示例,创建一个LinkedList对象,然后添加几个节点,最后输出链表的长度和各节点的值:
const list = new LinkedList();
list.append(1);
list.append(2);
list.append(3);
list.insert(2, 4);
list.remove(1);
console.log(list.length); // 3
console.log(list.get(0)); // 1
console.log(list.get(1)); // 4
console.log(list.get(2)); // 3
console.log(list.indexOf(4)); // 1
console.log(list.indexOf(5)); // -1
输出结果如下:
3
1
4
3
1
-1
LinkedList是一种常用的数据结构,用Javascript实现LinkedList可以加深对数据结构和算法的理解。在实现LinkedList时,需要注意几个问题: