定义

链表存在有充的元素集合,元素在内存中不是连续放置。每个元素由一个存储元素本身的节点和一个指向下一元素的引用(又称为指点或链接)组成
image.png
一列火车是由一系列车厢组成,每节车厢都相互连接。每节车厢是链表元素,车厢间的连接就是指针。

  • push(element)
  • insert(element, position)
  • getElementAt(index)
  • remove(element);
  • indexOf(element);
  • removeAt(postition)
  • isEmpty()
  • size()
  • toString()

    代码实现

    ```javascript function defaultEquals(a, b) { return a === b; }

class Node { constructor(element) { this.element = element; this.next = undefined; } }

class LinkedList { constructor(equalsFn = defaultEquals) { this.equalsFn = equalsFn; this.count = 0; this.head = undefined; }

push(element) { const node = new Node(element); let current; if (this.head == null) { // catches null && undefined this.head = node; } else { current = this.head; while (current.next != null) { current = current.next; } current.next = node; } this.count++; }

getElementAt(index) { if (index >= 0 && index <= this.count) { let node = this.head; for (let i = 0; i < index && node != null; i++) { node = node.next; } return node; } return undefined; }

insert(element, index) { if (index >= 0 && index <= this.count) { const node = new Node(element); if (index === 0) { const current = this.head; node.next = current; this.head = node; } else { const previous = this.getElementAt(index - 1); node.next = previous.next; previous.next = node; } this.count++; return true; } return false; }

removeAt(index) { if (index >= 0 && index < this.count) { let current = this.head; if (index === 0) { this.head = current.next; } else { const previous = this.getElementAt(index - 1); current = previous.next; previous.next = current.next; } this.count—; return current.element; } return undefined; }

remove(element) { const index = this.indexOf(element); return this.removeAt(index); }

indexOf(element) { let current = this.head; for (let i = 0; i < this.size() && current != null; i++) { if (this.equalsFn(element, current.element)) { return i; } current = current.next; } return -1; }

isEmpty() { return this.size() === 0; }

size() { return this.count; }

getHead() { return this.head; }

clear() { this.head = undefined; this.count = 0; }

toString() { if (this.head == null) { return ‘’; } let objString = ${this.head.element}; let current = this.head.next; for (let i = 1; i < this.size() && current != null; i++) { objString = ${objString} -> ${current.element}; current = current.next; } return objString; } }

  1. <a name="NeETc"></a>
  2. # 另一种封装方法
  3. ```javascript
  4. function Node (element) {
  5. this.element = element;
  6. this.next = undefined;
  7. }
  8. function LinkedList = (function () {
  9. class Node{
  10. constructor(element) {
  11. this.element = element;
  12. this.next = null;
  13. }
  14. }
  15. const length = new WeakMap();
  16. const head = new WeakMap();
  17. return class LinkedList() {
  18. constructor() {
  19. length.set(this, 0);
  20. head.set(this, null);
  21. }
  22. append(element) {
  23. let node = new Node(element),
  24. current;
  25. if(this.getHead() === null) {
  26. head.set(this, node);
  27. } else {
  28. current = this.getHead();
  29. while(current.next) {
  30. current = current.next;
  31. }
  32. current.next = node;
  33. let l = this.size();
  34. length.set(this, ++l);
  35. }
  36. }
  37. insert(position, element) {
  38. if(position >= 0 && position < this.size()) {
  39. let node = new Node(element),
  40. current = this.getHead(),
  41. index = 0,
  42. previous;
  43. if(position === 0){
  44. node.next = current;
  45. head.set(this, node);
  46. } else {
  47. while (index < position) {
  48. previous = current;
  49. current = current.next;
  50. }
  51. node.next = current;
  52. previous.next = node;
  53. }
  54. let l = this.size();
  55. length.set(this, ++l);
  56. return true;
  57. } else {
  58. return false;
  59. }
  60. }
  61. remove(element) {
  62. return this.removeAt(this.indexOf(element));
  63. }
  64. removeAt(position) {
  65. const size = this.size();
  66. if(position >= 0 && position < size) {
  67. let current = this.getHead(),
  68. index = 0;
  69. if(position === 0) {
  70. head.set(this, current.next);
  71. } else {
  72. while (index < position) {
  73. previous = current;
  74. current = current.next;
  75. }
  76. previous.next = current.next;
  77. }
  78. let l = this.size();
  79. length.set(this, --l);
  80. return true;
  81. }
  82. return false;
  83. }
  84. indexOf(element) {
  85. let current = head.get(this);
  86. for (let i = 0; i < this.size() && current != null; i++) {
  87. if (element === current.element) {
  88. return i;
  89. }
  90. current = current.next;
  91. }
  92. return -1;
  93. }
  94. isEmpty() {
  95. return length.get(this) === 0;
  96. }
  97. getHead() {
  98. return head.get(this);
  99. }
  100. size() {
  101. return length.get(this);
  102. }
  103. }
  104. })();