Double-Ended Queue Implementation
A growable ring-buffer deque with amortized O(1) pushes and pops at both ends, plus indexed snapshot access.
Code
// Double-ended queue backed by a growable ring buffer.
export class Deque {
#buffer = new Array(8);
#head = 0;
#size = 0;
pushBack(value) {
this.#ensure(this.#size + 1);
this.#buffer[(this.#head + this.#size) % this.#buffer.length] = value;
this.#size += 1;
return this;
}
pushFront(value) {
this.#ensure(this.#size + 1);
this.#head = (this.#head - 1 + this.#buffer.length) % this.#buffer.length;
this.#buffer[this.#head] = value;
this.#size += 1;
return this;
}
popFront() {
if (this.#size === 0) return undefined;
const value = this.#buffer[this.#head];
this.#buffer[this.#head] = undefined;
this.#head = (this.#head + 1) % this.#buffer.length;
this.#size -= 1;
return value;
}
popBack() {
if (this.#size === 0) return undefined;
this.#size -= 1;
const index = (this.#head + this.#size) % this.#buffer.length;
const value = this.#buffer[index];
this.#buffer[index] = undefined;
return value;
}
peekFront() {
return this.#size > 0 ? this.#buffer[this.#head] : undefined;
}
peekBack() {
return this.#size > 0
? this.#buffer[(this.#head + this.#size - 1) % this.#buffer.length]
: undefined;
}
get size() {
return this.#size;
}
toArray() {
const result = [];
for (let index = 0; index < this.#size; index += 1) {
result.push(this.#buffer[(this.#head + index) % this.#buffer.length]);
}
return result;
}
#ensure(capacity) {
if (capacity <= this.#buffer.length) return;
const next = new Array(this.#buffer.length * 2);
for (let index = 0; index < this.#size; index += 1) {
next[index] = this.#buffer[(this.#head + index) % this.#buffer.length];
}
this.#buffer = next;
this.#head = 0;
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.