Deque
import { Deque } from "velt/collections". A double-ended queue on a growable ring buffer.
Pushing and popping at either end is amortized O(1), and indexing is O(1). Where an array's
shift() and unshift() move every element, a deque moves none.
ts
import { Deque } from "velt/collections";
const q = Deque.from([2, 3]);
q.pushFront(1);
q.pushBack(4);
console.log(q.popFront(), q.popBack(), q.at(-1), q.length, q.toArray()); // 1 4 3 2 [ 2, 3 ]new Deque<T>(),Deque.from(xs),length/size,isEmpty(),clear().pushBack(v),pushFront(v).popBack(),popFront(): returnT | undefined(undefinedwhen empty).peekFront(),peekBack(),at(i: i64): return copies, orundefined; a negativeicounts from the back.toArray(): copies, front to back.forEach(f)visits the elements by position from the front and reads the length again after each call, as aforloop over an array does: when the callback changes the deque through another reference, elements pushed at the back are visited, and a push or pop at the front shifts the positions still to come.
An element type may allow null or undefined (Deque<i64 | null>): a stored null reads as
null, and a stored undefined reads as undefined, as an empty deque's popFront() does, the
same as with an array's shift().
A breadth-first walk
ts
import { Deque } from "velt/collections";
const edges = new Map<i64, i64[]>([[1, [2, 3]], [2, [4]], [3, [4]], [4, []]]);
const seen = new Set<i64>([1]);
const queue = new Deque<i64>();
queue.pushBack(1);
const order: i64[] = [];
while (!queue.isEmpty()) {
const n = queue.popFront()!;
order.push(n);
for (const next of edges.get(n) ?? []) {
if (!seen.has(next)) {
seen.add(next);
queue.pushBack(next);
}
}
}
console.log(order); // [ 1, 2, 3, 4 ]