当前位置:   article > 正文

数据结构 — 双向链表

双向循环链表中,用next指向下一个元素,last指向上一个元素,首结点为head(指向一个

双向链表,又称为双链表,是一种表示元素集合的线性数据结构,其中每个元素都指向下一个和上一个元素。双向链表中的第一个元素是 head,最后一个元素是 tail。

JavaScript 双向链表可视化

双向链表数据结构的每个元素必须具有以下属性:

  • value:元素的值
  • next:指向双向链表中下一个元素的指针(如果没有,则为 null)
  • previous:指向双向链表中上一个元素的指针(如果没有,则为 null)

双向链表数据结构的主要属性有:

  • size:双向链表中的元素个数
  • head:双向链表中的第一个元素
  • tail:双向链表中的最后一个元素

双向链表数据结构的主要操作有:

  • insertAt:在特定索引处插入元素
  • removeAt:删除特定索引处的元素
  • getAt:检索特定索引处的元素
  • clear:清空双向链表
  • reverse:反转双向链表中元素的顺序

JavaScript 实现

  1. class DoublyLinkedList {
  2. constructor() {
  3. this.nodes = []
  4. }
  5. get size() {
  6. return this.nodes.length
  7. }
  8. get head() {
  9. return this.size ? this.nodes[0] : null
  10. }
  11. get tail() {
  12. return this.size ? this.nodes[this.size - 1] : null
  13. }
  14. insertAt(index, value) {
  15. const previousNode = this.nodes[index - 1] || null
  16. const nextNode = this.nodes[index] || null
  17. const node = { value, next: nextNode, previous: previousNode }
  18. if (previousNode) previousNode.next = node
  19. if (nextNode) nextNode.previous = node
  20. this.nodes.splice(index, 0, node)
  21. }
  22. insertFirst(value) {
  23. this.insertAt(0, value)
  24. }
  25. insertLast(value) {
  26. this.insertAt(this.size, value)
  27. }
  28. getAt(index) {
  29. return this.nodes[index]
  30. }
  31. removeAt(index) {
  32. const previousNode = this.nodes[index - 1] || null
  33. const nextNode = this.nodes[index + 1] || null
  34. if (previousNode) previousNode.next = nextNode
  35. if (nextNode) nextNode.previous = previousNode
  36. return this.nodes.splice(index, 1)
  37. }
  38. clear() {
  39. this.nodes = []
  40. }
  41. reverse() {
  42. this.nodes = this.nodes.reduce((acc, { value }) => {
  43. const nextNode = acc[0] || null
  44. const node = { value, next: nextNode, previous: null }
  45. if (nextNode) nextNode.previous = node
  46. return [node, ...acc]
  47. }, [])
  48. }
  49. *[Symbol.iterator]() {
  50. yield* this.nodes
  51. }
  52. }
  • 创建一个具有 constructor 的类(class),为每个实例初始化一个空数组 nodes
  • 定义一个 size getter,它使用 Array.prototype.length 返回 nodes 数组中元素的数量。
  • 定义一个 head getter,它返回 nodes 数组的第一个元素,如果为空,则返回 null
  • 定义一个 tail getter,它返回 nodes 数组的最后一个元素,如果为空,则返回 null
  • 定义一个 insertAt() 方法,使用 Array.prototype.splice()nodes 数组中添加新对象,分别更新上一个元素的 next 键和下一个元素的 previous 键。
  • 定义两个便捷的方法 insertFirst()insertLast(),它们分别使用 insertAt() 方法在 nodes 数组的开头或结尾插入新元素。
  • 定义一个 getAt() 方法,用于检索给定 index 的元素。
  • 定义一个 removeAt() 方法,使用 Array.prototype.splice() 删除 nodes 数组中的对象,分别更新上一个元素的 next 键和下一个元素的 previous 键。
  • 定义一个 clear() 方法,清空 nodes 数组。
  • 定义一个 reverse() 方法,使用 Array.prototype.reduce() 和扩展运算符(...)来反转 nodes 数组的顺序,适当地更新每个元素的 nextprevious 键。
  • Symbol.iterator 定义一个生成器方法,使用 yield* 语法委托给 nodes 数组的迭代器。
  1. const list = new DoublyLinkedList()
  2. list.insertFirst(1)
  3. list.insertFirst(2)
  4. list.insertFirst(3)
  5. list.insertLast(4)
  6. list.insertAt(3, 5)
  7. list.size // 5
  8. list.head.value // 3
  9. list.head.next.value // 2
  10. list.tail.value // 4
  11. list.tail.previous.value // 5
  12. ;[...list].map((e) => e.value) // [3, 2, 1, 5, 4]
  13. list.removeAt(1) // 2
  14. list.getAt(1).value // 1
  15. list.head.next.value // 1
  16. ;[...list].map((e) => e.value) // [3, 1, 5, 4]
  17. list.reverse()
  18. ;[...list].map((e) => e.value) // [4, 5, 1, 3]
  19. list.clear()
  20. list.size // 0

以上内容译自 30 seconds of code 的 JavaScript Data Structures - Doubly Linked List

Leetcode 相关的双向链表题目

更多资料

Doubly Linked List

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/761443
推荐阅读
相关标签
  

闽ICP备14008679号