链接列表是你能学到的最重要的数据结构之一。
在一个链接列表中,每个项目都包含一个对其后面项目的引用。
我们可以从列表的开头开始,即head ,然后遍历列表中的所有项目,直到我们到达终点(tail )。
与数组相比,项目在实际的内存中并不是彼此相邻的(在低级别的编程语言中),也没有我们可以用来随机访问数组中某一项目的索引。
我们不能引用列表中间的一个项目,而不从头开始,因为我们不知道如何去引用它。
JavaScript没有链接列表的实现,所以我们现在要创建一个。
首先,我们创建Item 类,它将成为列表中每个项目的容器。
class Item {
next = null
value = null
constructor(value) {
this.value = value
}
}
我们有一个指向列表中下一个项目的指针,以及值。
然后我们定义了一个LinkedList 类,它将承载两个私有值:head 和tail 。
我们定义了一个append() 方法来向列表中添加一个项目。如果它是我们添加的第一个项目,那么这个项目既是列表的头也是列表的尾。否则,我们创建这个项目,并将其分配给尾部项目的next 属性。
class LinkedList {
#head = null
#tail = null
append = (value) => {
const item = new Item(value)
if (!this.#head) {
this.#head = item
this.#tail = item
return
}
this.#tail.next = item
this.#tail = item
}
size = () => {
let count = 1
let item = this.#head
if (!item) return 0
while ((item = item.next)) {
count++
}
return count
}
}
这就是我们可以使用它的方法。
const list = new LinkedList()
list.append(1)
list.append(2)
list.append(3)
我们可以添加一个size() 方法来返回列表的大小。
class LinkedList {
//...
size = () => {
let count = 1
let item = this.#head
if (!item) return 0
while ((item = item.next)) {
count++
}
return count
}
}
const list = new LinkedList()
list.size() //0
list.append(1)
list.size() //1
list.append(2)
list.append(3)
list.size() //3
我们如何在列表中找到一个项目,通过值?让我们实现一个方法来做到这一点。
class LinkedList {
//...
find = (value) => {
let count = 1
let item = this.#head
if (!item) return null
while ((item = item.next)) {
if (item.value === value) {
return item
}
}
return null
}
}
const list = new LinkedList()
list.append(1)
list.append(2)
list.append(3)
const item = list.find(2) //item.value === 2
如果我们想在链表中插入一个项目呢?我们已经有append() ,在列表的末尾插入项目。让我们实现一种方法,在一个特定的位置插入项目。
class LinkedList {
//...
insert = (index, value) => {
//check for out-of-bounds values
if (index < 0 || index > this.size()) return
const node = new Item(value)
let current = this.#head
let previous
if (index === 0) {
//first position
node.next = current
this.#head = node
} else {
let i = 0
while (i++ < index) {
previous = current
current = current.next
}
node.next = current
previous.next = node
}
}
}
const list = new LinkedList()
list.append(1)
list.append(2)
list.append(3)
list.insert(2, 'a')
list.size() //4
另一种类型的链表是双链表,其中每个项目也包含一个到前一个元素的链接。