链表,存储的是有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。如下图展示了一个链表的结构。

    image.png

    1. class LinkedList {
    2. constructor() {
    3. this.count = 0;
    4. this.head = null;
    5. }
    6. equalsFn(a, b) {
    7. return a === b;
    8. }
    9. nodeFactory(element) {
    10. return {
    11. element,
    12. next: null
    13. }
    14. }
    15. push(element) {
    16. const node = this.nodeFactory(element);
    17. if (this.head) {
    18. let current = this.head;
    19. while (current.next) {
    20. current = current.next;
    21. }
    22. current.next = node;
    23. } else {
    24. this.head = node;
    25. }
    26. this.count++;
    27. }
    28. removeAt(index) {
    29. if (index < 0 || index > this.count) {
    30. return;
    31. }
    32. let current = this.head;
    33. if (index === 0) {
    34. this.head = current.next;
    35. } else {
    36. let previous = this.getElementAt(index - 1);
    37. current = previous.next;
    38. previous.next = current.next;
    39. }
    40. this.count--;
    41. return current.element;
    42. }
    43. insert(element, index) {
    44. if (index < 0 || index > this.count) {
    45. return;
    46. }
    47. let node = this.nodeFactory(element);
    48. if (index === 0) {
    49. node.next = this.head;
    50. this.head = element;
    51. } else {
    52. let previous = this.getElementAt(index - 1);
    53. let current = previous.next;
    54. node.next = current;
    55. previous.next = node;
    56. }
    57. this.count++;
    58. return true;
    59. }
    60. indexOf(element) {
    61. let current = this.head;
    62. for (let i = 0; i < this.count; i++) {
    63. if (this.equalsFn(element, current.element)) {
    64. return i;
    65. }
    66. current = current.next;
    67. }
    68. return -1;
    69. }
    70. remove(element) {
    71. let index = this.indexOf(element);
    72. return this.removeAt(index);
    73. }
    74. size() {
    75. return this.count;
    76. }
    77. isEmpty() {
    78. return this.size() === 0;
    79. }
    80. getHead() {
    81. return this.head;
    82. }
    83. getElementAt(index) {
    84. if (index < 0 || index > this.count) {
    85. return;
    86. }
    87. let current = this.head;
    88. for (let i = 0; i < index; i++) {
    89. current = current.next;
    90. }
    91. return current;
    92. }
    93. toString() {
    94. if (!this.head) return '';
    95. let str = `${this.head.element}`;
    96. let current = this.head.next;
    97. for (let i = 1; i < this.count; i++) {
    98. str += `, ${current.element}`;
    99. current = current.next;
    100. }
    101. return str;
    102. }
    103. }