You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
1.5 KiB
90 lines
1.5 KiB
/* |
|
How it works: |
|
`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. |
|
*/ |
|
|
|
class Node { |
|
value; |
|
next; |
|
|
|
constructor(value) { |
|
this.value = value; |
|
} |
|
} |
|
|
|
export default class Queue { |
|
#head; |
|
#tail; |
|
#size; |
|
|
|
constructor() { |
|
this.clear(); |
|
} |
|
|
|
enqueue(value) { |
|
const node = new Node(value); |
|
|
|
if (this.#head) { |
|
this.#tail.next = node; |
|
this.#tail = node; |
|
} else { |
|
this.#head = node; |
|
this.#tail = node; |
|
} |
|
|
|
this.#size++; |
|
} |
|
|
|
dequeue() { |
|
const current = this.#head; |
|
if (!current) { |
|
return; |
|
} |
|
|
|
this.#head = this.#head.next; |
|
this.#size--; |
|
|
|
// Clean up tail reference when queue becomes empty |
|
if (!this.#head) { |
|
this.#tail = undefined; |
|
} |
|
|
|
return current.value; |
|
} |
|
|
|
peek() { |
|
if (!this.#head) { |
|
return; |
|
} |
|
|
|
return this.#head.value; |
|
|
|
// TODO: Node.js 18. |
|
// return this.#head?.value; |
|
} |
|
|
|
clear() { |
|
this.#head = undefined; |
|
this.#tail = undefined; |
|
this.#size = 0; |
|
} |
|
|
|
get size() { |
|
return this.#size; |
|
} |
|
|
|
* [Symbol.iterator]() { |
|
let current = this.#head; |
|
|
|
while (current) { |
|
yield current.value; |
|
current = current.next; |
|
} |
|
} |
|
|
|
* drain() { |
|
while (this.#head) { |
|
yield this.dequeue(); |
|
} |
|
} |
|
}
|
|
|