index.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. How it works:
  3. `this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.
  4. */
  5. class Node {
  6. value;
  7. next;
  8. constructor(value) {
  9. this.value = value;
  10. }
  11. }
  12. export default class Queue {
  13. #head;
  14. #tail;
  15. #size;
  16. constructor() {
  17. this.clear();
  18. }
  19. enqueue(value) {
  20. const node = new Node(value);
  21. if (this.#head) {
  22. this.#tail.next = node;
  23. this.#tail = node;
  24. } else {
  25. this.#head = node;
  26. this.#tail = node;
  27. }
  28. this.#size++;
  29. }
  30. dequeue() {
  31. const current = this.#head;
  32. if (!current) {
  33. return;
  34. }
  35. this.#head = this.#head.next;
  36. this.#size--;
  37. return current.value;
  38. }
  39. peek() {
  40. if (!this.#head) {
  41. return;
  42. }
  43. return this.#head.value;
  44. // TODO: Node.js 18.
  45. // return this.#head?.value;
  46. }
  47. clear() {
  48. this.#head = undefined;
  49. this.#tail = undefined;
  50. this.#size = 0;
  51. }
  52. get size() {
  53. return this.#size;
  54. }
  55. * [Symbol.iterator]() {
  56. let current = this.#head;
  57. while (current) {
  58. yield current.value;
  59. current = current.next;
  60. }
  61. }
  62. }