概念和用途

数组存在长度局限

数组的效率不如链表快,js中是用对象来实现的数组

链表可以用在任何一维数组的位置

关键定义

链表是一系列节点组成的集合,每个节点都是用一个对象的引用指向它的后继,指向另一个节点的引用叫做。(也就是箭头线的那个连接关系)

单向链表和双向链表

  1. // 单向链表
  2. // 1. 抽象一个node节点
  3. function Node(ele) {
  4. this.element = ele;
  5. this.next = null;
  6. }
  7. // 2. 抽象单向链操作类
  8. function LList() {
  9. // 2.1 头节点
  10. this.head = new Node('head');
  11. // 2.2 find方法,查找某个节点
  12. this.find = find;
  13. // 2.3 insert 插入
  14. this.insert = insert
  15. // 2.3 display 遍历链表
  16. this.display = display
  17. // 2.4 寻找上一个
  18. this.findPrevious = findPrevious
  19. // 2.5 移除(依赖于寻找上一个)
  20. this.remove = remove
  21. // 2.6 check一个节点是否存在,存在才可以继续find
  22. this.check = check
  23. }
  24. function check(ele) {
  25. var currNode = this.head;
  26. while (currNode != null && currNode.element != ele) {
  27. currNode = currNode.next;
  28. }
  29. if (currNode == null) return false;
  30. return true
  31. }
  32. function find(ele) {
  33. var currNode = this.head;
  34. while (currNode.element != ele) {
  35. // 课程里面没有这个,导致find一个不存在的节点时候,死循环了,通过判断返回最后一个节点即可
  36. if (currNode.next == null) {
  37. return currNode;
  38. }
  39. currNode = currNode.next;
  40. }
  41. return currNode;
  42. }
  43. function insert(ele, target) {
  44. // 1. 现有新节点
  45. var newNode = new Node(ele);
  46. // 2. 查找要插入的节点
  47. if (!this.check(target)) {
  48. console.log('无法插入')
  49. return
  50. }
  51. var currNode = this.find(target);
  52. // 3. 开始插入(变换指针方向)
  53. newNode.next = currNode.next;
  54. currNode.next = newNode;
  55. }
  56. function display() {
  57. var currNode = this.head;
  58. while (currNode.next != null) {
  59. console.log(currNode.next.element);
  60. // 第一次实现没写地下这个,导致死循环了
  61. currNode = currNode.next
  62. }
  63. console.log('--------diplay done------')
  64. }
  65. function findPrevious(ele) {
  66. var currNode = this.head;
  67. if (currNode.element == ele) {
  68. return currNode
  69. }
  70. // 第一次实现写成了 currNode!= null && currNode.element!= ele 大概是脑子进屎了吧
  71. while(currNode.next!= null && currNode.next.element!= ele) {
  72. currNode = currNode.next
  73. }
  74. return currNode
  75. }
  76. function remove(ele) {
  77. if(!this.check(ele)){
  78. console.log('不存在节点,不必删除')
  79. return
  80. }
  81. var currNode = this.find(ele)
  82. var prevNode = this.findPrevious(ele)
  83. prevNode.next = currNode.next
  84. currNode.next = null
  85. }
  86. var pList = new LList();
  87. pList.insert('p2', 'head');
  88. pList.insert('p3', 'p2');
  89. pList.insert('p4', 'p3')
  90. // pList.display();
  91. console.log('-----表演移除和寻找上一个------')
  92. console.log(pList.findPrevious('p99'))
  93. pList.remove('p33')
  94. pList.remove('p3')
  95. pList.display();
  1. // 双向链表 理解透双向链表的图示然后根据理解编写即可
  2. // 1. 抽象一个node节点
  3. function Node(ele) {
  4. this.element = ele;
  5. this.next = null;
  6. // 比单向链表多了前驱节点
  7. this.previous = null;
  8. }
  9. // 2. 抽象双向链操作类
  10. function LList() {
  11. // 2.1 头节点
  12. this.head = new Node('head');
  13. // 2.2 find方法,查找某个节点
  14. this.find = find;
  15. // 2.3 insert 插入
  16. this.insert = insert
  17. // 2.3 display 遍历链表
  18. this.display = display
  19. // // 2.4 寻找上一个 双向链表可以直接访问
  20. // this.findPrevious = findPrevious
  21. // 2.4 反向遍历
  22. this.displayReverse = displayReverse
  23. // 2.4.1 直接到尾节点
  24. this.findLast = findLast
  25. // 2.5 移除(依赖于寻找上一个)
  26. this.remove = remove
  27. // 2.6 check一个节点是否存在,存在才可以继续find
  28. this.check = check
  29. }
  30. function check(ele) {
  31. var currNode = this.head;
  32. while (currNode != null && currNode.element != ele) {
  33. currNode = currNode.next;
  34. }
  35. if (currNode == null) return false;
  36. return true
  37. }
  38. function find(ele) {
  39. var currNode = this.head;
  40. while (currNode.element != ele) {
  41. // 课程里面没有这个,导致find一个不存在的节点时候,死循环了,通过判断返回最后一个节点即可
  42. if (currNode.next == null) {
  43. return currNode;
  44. }
  45. currNode = currNode.next;
  46. }
  47. return currNode;
  48. }
  49. function insert(ele, target) {
  50. // 1. 现有新节点
  51. var newNode = new Node(ele);
  52. // 2. 查找要插入的节点
  53. if (!this.check(target)) {
  54. console.log('无法插入')
  55. return
  56. }
  57. var currNode = this.find(target);
  58. newNode.next = currNode.next;
  59. newNode.previous = currNode
  60. currNode.next = newNode
  61. // 判断是否是尾节点
  62. if (newNode.next != null) {
  63. newNode.next.previous = newNode
  64. }
  65. }
  66. function display() {
  67. var currNode = this.head;
  68. while (currNode.next != null) {
  69. console.log(currNode.next.element);
  70. // 第一次实现没写地下这个,导致死循环了
  71. currNode = currNode.next
  72. }
  73. console.log('--------diplay done------')
  74. }
  75. function findPrevious(ele) {
  76. var currNode = this.head;
  77. if (currNode.element == ele) {
  78. return currNode
  79. }
  80. // 第一次实现写成了 currNode!= null && currNode.element!= ele 大概是脑子进屎了吧
  81. while(currNode.next!= null && currNode.next.element!= ele) {
  82. currNode = currNode.next
  83. }
  84. return currNode
  85. }
  86. function remove(ele) {
  87. if(!this.check(ele)){
  88. console.log('不存在节点,不必删除')
  89. return
  90. }
  91. var currNode = this.find(ele)
  92. var prevNode = currNode.previous
  93. prevNode.next = currNode.next
  94. currNode.next.previous = prevNode
  95. currNode.next = null
  96. }
  97. function displayReverse() {
  98. var currNode = this.findLast()
  99. while(currNode.previous != null) {
  100. console.log(currNode.element)
  101. currNode = currNode.previous
  102. }
  103. }
  104. function findLast() {
  105. var currNode = this.head
  106. while(currNode.next != null) {
  107. currNode = currNode.next
  108. }
  109. return currNode
  110. }
  111. var pList = new LList();
  112. pList.insert('p2', 'head');
  113. pList.insert('p3', 'p2');
  114. pList.insert('p4', 'p3')
  115. // pList.display();
  116. console.log('-----表演移除和寻找最后一个------')
  117. // console.log(pList.findLast())
  118. // pList.displayReverse()
  119. // console.log(pList.findPrevious('p99'))
  120. pList.remove('p33')
  121. pList.remove('p3')
  122. pList.displayReverse();