认识链表
image.png
链表是一个节点,通过节点存储值

  1. function Node (element) { // 链表的存储方式,是通过节点方式存储
  2. this.element = element;
  3. // next 指针, 指向的它的下一个节点
  4. this.next = next;
  5. }

链表是有序的: 不一定是连续的存储空间。

链表具有的方法

  • append 往链表尾部添加元素
  • insert 特定位置添加
  • remove 根据内容移除项
  • removeAt 根据索引移除项
  • indexOf 找到索引
  • isEmpty 判断链表是否为空
  • size 链表的长度

链表的定义

image.png

就是一个没有添加方法的链表

  1. // 定义链表
  2. // 同样使用 ES6 class 和立即执行函数
  3. let LinkedList = (function() {
  4. // 定义一个链表
  5. class Node {
  6. // 初始化链表
  7. constructor(element) {
  8. this.element = element;
  9. this.next = null;
  10. }
  11. }
  12. // 定义链表初始化值
  13. let length = new WeakMap(); // 初始时,链表的长度
  14. let head = new WeakMap(); // 初始时, 链表的头部
  15. // 返回的链表
  16. return class LinkedList {
  17. constructor() {
  18. // 初始化
  19. length.set(this, 0);
  20. head.set(this, null);
  21. }
  22. }
  23. })();
  24. let list = new LinkedList();

定义具有方法的链表

  1. // 定义链表
  2. // 同样使用 ES6 class 和立即执行函数
  3. let LinkedList = (function() {
  4. // 定义一个链表
  5. class Node {
  6. // 初始化链表
  7. constructor(element) {
  8. this.element = element;
  9. this.next = null;
  10. }
  11. }
  12. // 定义链表初始化值
  13. let length = new WeakMap(); // 初始时,链表的长度
  14. let head = new WeakMap(); // 初始时, 链表的头部
  15. // 返回的链表
  16. return class LinkedList {
  17. constructor() {
  18. // 初始化, 当前的链表
  19. length.set(this, 0); // 长度为0
  20. head.set(this, null); // 头部数据为 null
  21. }
  22. // 链表的方法
  23. // append 在链表最后添加节点
  24. append(element) {
  25. // 创建节点
  26. let node = new Node(element),
  27. // 声明一个变量,用于保存链表的头部数据
  28. current;
  29. // 判断链表是否有数据
  30. if (this.getHeader() === null) {
  31. // 当链表为空的情况下
  32. head.set(this, node); // 直接添加
  33. } else {
  34. // 链表头部不为空
  35. // 找到链表最末的节点, 让最末的节点的 next 指向添的node
  36. current = this.getHeader(); // 获取当前的head
  37. // 判断当前节点的next存在
  38. while (current.next) {
  39. // next ++ ,一直循环
  40. current = current.next;
  41. }
  42. // 进行while循环完后,current 就为最后的节点。
  43. // 然后进行赋值
  44. current.next = node;
  45. // 赋值后,让链表长度 +1
  46. // 使用size获取链表的长度
  47. let l = this.size();
  48. l++; // 让链表的长度加一
  49. length.set(this, l); // 重新赋值
  50. }
  51. }
  52. // 在链表任何位置插入数据
  53. insert(position, element) {
  54. // position : 链表的位置
  55. // element : 插入的节点数据
  56. // 判断当前链表
  57. if (position >= 0 && position <= this.size()) {
  58. // 创建节点
  59. let node = new Node(element),
  60. // 使用current 保存到获取链表的头部
  61. current = this.getHeader(),
  62. index = 0,
  63. previous;
  64. // 判断链表
  65. if (position === 0) {
  66. // 表示在链表的头部插入数据
  67. node.next = current; // 将初始的链表的指针设置为新创建的node
  68. head.set(this, node); // 链表赋值
  69. } else {
  70. // 表示插入的节点在某一个节点前
  71. while (index++ < position) {
  72. previous = current;
  73. current = current.next;
  74. }
  75. // 将它们的next() 指向另一个node
  76. node.next = current;
  77. previous.next = node;
  78. }
  79. // 让length ++
  80. // 使用size获取链表的长度
  81. let l = this.size();
  82. l++; // 让链表的长度加一
  83. length.set(this, l); // 重新赋值
  84. // 追加后,返回head, 查看head
  85. console.log(this.getHeader()); // 返回是否插入成功
  86. return true;
  87. } else {
  88. // 插入不成功
  89. return false;
  90. }
  91. }
  92. // 判断链表的头部
  93. getHeader() {
  94. return head.get(this);
  95. }
  96. // 返回链表的长度
  97. size() {
  98. return length.get(this);
  99. }
  100. }
  101. })();
  102. let list = new LinkedList();
  103. list.append(0);
  104. list.append(1);
  105. list.append(2);
  106. list.append(3);
  107. // insert方法的实现和数组的插入方法一样
  108. // var arr = [0, 1, 2, 3, 4];
  109. // arr.splice(2, 0, 1.5);
  110. // console.log(arr);
  111. console.log(list.insert(2, 1.5)); // 2: 插入的位置, 1.5 插入的数据