单向链表

  1. class Node {
  2. constructor(element) {
  3. this.element = element;
  4. this.next = null;
  5. }
  6. }
  7. class LinkedList {
  8. constructor() {
  9. this.size = 0;
  10. this.head = null;
  11. }
  12. /**
  13. * @method 尾部追加数据
  14. * @param {any} element 追加数据
  15. */
  16. append(element) {
  17. let node = new Node(element);
  18. if (this.head === null) {
  19. this.head = node;
  20. } else {
  21. let current = this.getNode(this.size - 1);
  22. current.next = node;
  23. }
  24. this.size++;
  25. }
  26. /**
  27. * @method 指定位置追加数据
  28. * @param {Number} position 位置
  29. * @param {any} element 追加数据
  30. */
  31. appendAt(position, element) {
  32. if (position < 0 || position > this.size) {
  33. throw new Error("position out range");
  34. }
  35. let node = new Node(element);
  36. if (position === 0) {
  37. node.next = this.head;
  38. this.head = node;
  39. } else {
  40. let pre = this.getNode(position - 1);
  41. node.next = pre.next;
  42. pre.next = node;
  43. }
  44. this.size++;
  45. }
  46. /**
  47. * @method 删除指定位置数据
  48. * @param {Number} position 位置
  49. */
  50. removeAt(position) {
  51. if (position < 0 || position >= this.size) {
  52. throw new Error("position out range");
  53. }
  54. let current = this.head;
  55. if (position === 0) {
  56. this.head = current.next;
  57. } else {
  58. let pre = this.getNode(position - 1);
  59. current = pre.next;
  60. pre.next = current.next;
  61. }
  62. this.size--;
  63. }
  64. /**
  65. * @method 修改指定位置数据
  66. * @param {Number} position 位置
  67. * @param {any} element 追加数据
  68. */
  69. update(position, element) {
  70. if (position < 0 || position >= this.size) {
  71. throw new Error("position out range");
  72. }
  73. let pre = this.getNode(position);
  74. pre.element = element;
  75. }
  76. /**
  77. * @method 查找指定位置数据
  78. * @param {Number} position 位置
  79. * @return {any} 返回数据
  80. */
  81. getData(position) {
  82. if (position < 0 || position >= this.size) {
  83. throw new Error("position out range");
  84. }
  85. let pre = this.getNode(position);
  86. return pre.element;
  87. }
  88. /**
  89. * @method 查找指定数据索引
  90. * @param {any} element
  91. * @return {Number} 索引
  92. */
  93. indexOf(element) {
  94. let current = this.head;
  95. // let i = 0;
  96. // while (current) {
  97. // if (current.element === element) return i;
  98. // current = current.next;
  99. // i++;
  100. // }
  101. for (let i = 0; i < this.size; i++) {
  102. if (current.element === element) {
  103. return i;
  104. }
  105. current = current.next;
  106. }
  107. return -1;
  108. }
  109. /**
  110. * @method 返回链表长度
  111. * @return {Number} 链表长度
  112. */
  113. get length() {
  114. return this.size;
  115. }
  116. getNode(index) {
  117. if (index < 0 || index >= this.size) {
  118. throw new Error("out range");
  119. }
  120. let current = this.head;
  121. // let i = 0;
  122. // while (i++ < index) {
  123. // current = current.next;
  124. // }
  125. for (let i = 0; i < index; i++) {
  126. current = current.next;
  127. }
  128. return current;
  129. }
  130. }
  131. let ll = new LinkedList();
  132. ll.append(1);
  133. ll.append(2);
  134. // ll.append(3);
  135. // ll.append(4);
  136. ll.appendAt(2, 3);
  137. ll.appendAt(3, 4);
  138. // ll.appendAt(3, 2);
  139. // ll.removeAt(0);
  140. // ll.removeAt(1);
  141. console.log(ll.getData(3));
  142. // console.log(ll.indexOf(1));
  143. // console.log(ll.indexOf(2));
  144. // console.log(ll.indexOf(3));
  145. // console.log(ll.indexOf(4));
  146. // console.log(ll.indexOf(5));
  147. console.dir(ll, {
  148. depth: 100,
  149. });
  150. console.log(ll.length);
  151. // setTimeout(() => {
  152. // ll.update(3, 9);
  153. // console.dir(ll, {
  154. // depth: 100,
  155. // });
  156. // }, 1000);

双向链表

  1. class DoublyNode {
  2. constructor(element) {
  3. this.element = element;
  4. this.prev = null;
  5. this.next = null;
  6. }
  7. }
  8. class DoublyLinkedList {
  9. constructor() {
  10. this.size = 0;
  11. this.head = null;
  12. this.tail = null;
  13. }
  14. /**
  15. * @method 尾部追加数据
  16. * @param {any} element 追加数据
  17. */
  18. append(element) {
  19. let node = new DoublyNode(element);
  20. if (this.head === null) {
  21. this.head = node;
  22. this.tail = node;
  23. } else {
  24. this.tail.next = node;
  25. node.prev = this.tail;
  26. this.tail = node;
  27. }
  28. this.size++;
  29. }
  30. /**
  31. * @method 指定位置追加数据
  32. * @param {*} position 位置
  33. * @param {*} element 追加数据
  34. */
  35. appendAt(position, element) {
  36. if (position < 0 || position > this.size) {
  37. throw new Error("position out range");
  38. }
  39. let node = new DoublyNode(element);
  40. if (position === 0) {
  41. if (this.head === null) {
  42. this.head = node;
  43. this.tail = node;
  44. } else {
  45. node.next = this.head;
  46. this.head.perv = node;
  47. this.head = node;
  48. }
  49. } else if (position === this.size) {
  50. this.tail.next = node;
  51. node.prev = this.tail;
  52. this.tail = node;
  53. } else {
  54. let pre = this.getNode(position - 1);
  55. pre.next = node;
  56. node.prev = pre;
  57. node.next = pre.next;
  58. pre.prev = node;
  59. }
  60. this.size++;
  61. }
  62. /**
  63. * @method 删除指定位置数据
  64. * @param {*} position 位置
  65. */
  66. removeAt(position) {
  67. if (position < 0 || position >= this.size) {
  68. throw new Error("position out range");
  69. }
  70. let current = this.head;
  71. if (position === 0) {
  72. if (this.size === 1) {
  73. this.head = null;
  74. this.tail = null;
  75. } else {
  76. this.head = current.next;
  77. this.head.prev = null;
  78. }
  79. } else if (position === this.size - 1) {
  80. this.tail.prev.next = null;
  81. this.tail = this.tail.prev;
  82. } else {
  83. let pre = this.getNode(position - 1);
  84. current = pre.next;
  85. pre.next = current.next;
  86. }
  87. this.size--;
  88. }
  89. /**
  90. * @method 修改指定位置数据
  91. * @param {Number} position 位置
  92. * @param {any} element 追加数据
  93. * TODO: 性能优化点 this.size / 2 > position 从头向后遍历, 反之则反
  94. */
  95. update(position, element) {
  96. if (position < 0 || position >= this.size) {
  97. throw new Error("position out range");
  98. }
  99. let pre = this.getNode(position);
  100. pre.element = element;
  101. }
  102. /**
  103. * @method 查找指定位置数据
  104. * @param {Number} position 位置
  105. * @return {any} 返回数据
  106. * TODO: 性能优化点 this.size / 2 > position 从头向后遍历, 反之则反
  107. */
  108. getData(position) {
  109. if (position < 0 || position >= this.size) {
  110. throw new Error("position out range");
  111. }
  112. let pre = this.getNode(position);
  113. return pre.element;
  114. }
  115. /**
  116. * @method 查找指定数据索引
  117. * @param {Number} element
  118. * @return {Number} 索引
  119. */
  120. indexOf(element) {
  121. let current = this.head;
  122. for (let i = 0; i < this.size; i++) {
  123. if (current.element === element) {
  124. return i;
  125. }
  126. current = current.next;
  127. }
  128. return -1;
  129. }
  130. /**
  131. * @method 返回链表长度
  132. * @return {Number} 链表长度
  133. */
  134. get length() {
  135. return this.size;
  136. }
  137. getNode(index) {
  138. if (index < 0 || index >= this.size) {
  139. throw new Error("out range");
  140. }
  141. let current = this.head;
  142. for (let i = 0; i < index; i++) {
  143. current = current.next;
  144. }
  145. return current;
  146. }
  147. }
  148. let ll = new DoublyLinkedList();
  149. ll.append(1);
  150. ll.append(2);
  151. ll.append(3);
  152. ll.append(4);
  153. // ll.appendAt(2, 3);
  154. // ll.appendAt(3, 4);
  155. // ll.appendAt(3, 2);
  156. // ll.removeAt(0);
  157. // ll.removeAt(1);
  158. // console.log(ll.getData(3));
  159. // console.log(ll.indexOf(1));
  160. // console.log(ll.indexOf(2));
  161. // console.log(ll.indexOf(3));
  162. // console.log(ll.indexOf(4));
  163. // console.log(ll.indexOf(5));
  164. console.dir(ll, {
  165. depth: 100,
  166. });
  167. console.log(ll.length);
  168. setTimeout(() => {
  169. ll.update(3, 9);
  170. console.dir(ll, {
  171. depth: 100,
  172. });
  173. }, 1000);

单向循环链表

双向循环链表

环形链表