ArrayQueue.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. /**
  7. * @template T
  8. */
  9. class ArrayQueue {
  10. /**
  11. * @param {Iterable<T>=} items The initial elements.
  12. */
  13. constructor(items) {
  14. /** @private @type {T[]} */
  15. this._list = items ? Array.from(items) : [];
  16. /** @private @type {T[]} */
  17. this._listReversed = [];
  18. }
  19. /**
  20. * Returns the number of elements in this queue.
  21. * @returns {number} The number of elements in this queue.
  22. */
  23. get length() {
  24. return this._list.length + this._listReversed.length;
  25. }
  26. /**
  27. * Empties the queue.
  28. */
  29. clear() {
  30. this._list.length = 0;
  31. this._listReversed.length = 0;
  32. }
  33. /**
  34. * Appends the specified element to this queue.
  35. * @param {T} item The element to add.
  36. * @returns {void}
  37. */
  38. enqueue(item) {
  39. this._list.push(item);
  40. }
  41. /**
  42. * Retrieves and removes the head of this queue.
  43. * @returns {T | undefined} The head of the queue of `undefined` if this queue is empty.
  44. */
  45. dequeue() {
  46. if (this._listReversed.length === 0) {
  47. if (this._list.length === 0) return undefined;
  48. if (this._list.length === 1) return this._list.pop();
  49. if (this._list.length < 16) return this._list.shift();
  50. const temp = this._listReversed;
  51. this._listReversed = this._list;
  52. this._listReversed.reverse();
  53. this._list = temp;
  54. }
  55. return this._listReversed.pop();
  56. }
  57. /**
  58. * Finds and removes an item
  59. * @param {T} item the item
  60. * @returns {void}
  61. */
  62. delete(item) {
  63. const i = this._list.indexOf(item);
  64. if (i >= 0) {
  65. this._list.splice(i, 1);
  66. } else {
  67. const i = this._listReversed.indexOf(item);
  68. if (i >= 0) this._listReversed.splice(i, 1);
  69. }
  70. }
  71. [Symbol.iterator]() {
  72. let i = -1;
  73. let reversed = false;
  74. return {
  75. next: () => {
  76. if (!reversed) {
  77. i++;
  78. if (i < this._list.length) {
  79. return {
  80. done: false,
  81. value: this._list[i]
  82. };
  83. }
  84. reversed = true;
  85. i = this._listReversed.length;
  86. }
  87. i--;
  88. if (i < 0) {
  89. return {
  90. done: true,
  91. value: undefined
  92. };
  93. }
  94. return {
  95. done: false,
  96. value: this._listReversed[i]
  97. };
  98. }
  99. };
  100. }
  101. }
  102. module.exports = ArrayQueue;