class DirectedGraph {
constructor() {
this.edges = new Map();
}
static fromEdges(edges) {
const digraph = new DirectedGraph();
for (const [frm, to] of edges) digraph.addEdge(frm, to);
return digraph;
}
addEdge(frm, to) {
let terminalNodes = this.edges.get(frm);
if (terminalNodes == null) {
terminalNodes = new Set();
this.edges.set(frm, terminalNodes);
}
terminalNodes.add(to);
}
walkDfs(source) {
const seen = this._dfsIter(source, new Set());
return new Set([...seen]);
}
*_dfsIter(source, seen) {
if (seen.has(source)) {
return;
}
seen.add(source);
yield source;
if (this.edges.has(source)) {
const targets = this.edges.get(source);
for (const target of targets.values()) {
yield* this._dfsIter(target, seen);
}
}
}
}