数组在添加、移除会导致后续元素位移,性能开销大。
而链表在添加与删除时不会导致其余元素位移。
链表的缺点是无法根据索引快速定位元素。
小结:
获取、修改元素时,数组效率高。
添加、删除元素时、链表效率高。
链表的实现
addAtTail 尾部添加节点
addAtHead 头部添加节点
addAtIndex 指定位置添加节点
get 获取节点
removeAtIndex 删除指定节点
// 节点类
class LinkedNode {
constructor(value) {
this.value = value
this.next = null
}
}
// 链表类
class LinkedList {
constructor() {
this.count = 0
this.head = null
}
// 尾部添加节点
addAtTail(value) {
// 创建新节点
const node = new LinkedNode(value)
// 检测链表是否存在数据
if (this.count === 0) {
this.head = node
} else {
// 找到链表尾部节点
let cur = this.head
while (cur.next) {
cur = cur.next
}
cur.next = node
}
this.count++
}
// 头部添加节点
addAtHead(value) {
const node = new LinkedNode(value)
if (this.count === 0) {
this.head = node
} else {
// 将 node 添加到 head 的前面
node.next = this.head
this.head = node
}
this.count++
}
// 根据索引获取节点
get(index) {
if (this.count === 0 || this.index < 0 || index >= count) {
return
}
// 迭代链表,找到对应节点
let cur = head
for(let i = 0; i < index; i++) {
cur = cur.next
}
return cur
}
// 根据索引添加节点
addAtIndex(value, index) {
if (this.count === 0 || index >= count) {
return
}
// 如果 index <= 0,添加到头部
if (index <= 0) {
this.addAtHead(value)
return
}
const prev = this.get(index - 1)
const next = prev.next
const node = new LinkedNode(value)
prev.next = node
node.next = next
this.count++
}
// 根据索引删除
removeAtIndex(index) {
if (this.count === 0 || this.index < 0 || this.index >= this.count) {
return
}
if (index === 0) {
this.head = this.head.next
return
}
const prev = this.get(index - 1)
prev.next = prev.next.next
this.count--
}
}
链表的多种形式
双向链表
循环链表(环形链表)
1