【发布时间】:2021-05-24 01:30:14
【问题描述】:
破解方法:hasPathDFSBroken
工作版本:hasPathDFS
工作版本添加了一个人为的参数以使其工作,我宁愿避免。
我试图理解为什么在损坏的版本中,当调用堆栈作为 currNode 在 LIM 开始展开并作为 currentNode 返回到 MEX 时,为什么它不会在 MEX 的邻居上恢复未完成的 for 循环?
任何帮助将不胜感激。谢谢!
const airports = "PHX BKK OKC JFK LAX MEX EZE HEL LOS LAP LIM".split(" ");
const routes = [
["PHX", "LAX"],
["PHX", "JFK"],
["JFK", "OKC"],
["JFK", "HEL"],
["JFK", "LOS"],
["MEX", "LAX"],
["MEX", "BKK"],
["MEX", "LIM"],
["MEX", "EZE"],
["LIM", "BKK"],
];
class Node {
constructor(data) {
this.data = data;
this.neighbors = new Map();
}
addNeighbor(node) {
this.neighbors.set(node.data, node);
return this.neighbors.size;
}
getNeighbors() {
return this.neighbors;
}
}
class Graph {
constructor(edgeDirection = Graph.UNDIRECTED) {
this.nodes = new Map();
this.edgeDirection = edgeDirection;
}
/* ???
When the call stack starts unwinding at LIM as currNode and it gets back to MEX
as currNode, why doesn't the unfinished for loop resume over MEX's neighbors?
*/
hasPathDFSBroken(
start,
destination,
currNode = this.nodes.get(start),
visited = new Map()
) {
if (!currNode) {
return false;
}
visited.set(currNode.data, 1);
console.log(
"currNode:",
currNode.data,
"| neighbors:",
[...currNode.getNeighbors().keys()],
"| visited:",
[...visited.keys()]
);
for (const [neighborData, neighborNode] of currNode
.getNeighbors()
.entries()) {
console.log("currNeighbor:", neighborData);
if (neighborData === destination) {
return true;
}
if (!visited.has(neighborData)) {
return this.hasPathDFSBroken(start, destination, neighborNode, visited);
}
}
return false;
}
// Works but uses contrived found param for pass by ref.
hasPathDFS(
start,
destination,
currNode = this.nodes.get(start),
visited = new Map(),
found = { res: false }
) {
if (!currNode) {
return false;
}
visited.set(currNode.data, 1);
console.log(
"currNode:",
currNode.data,
"| neighbors:",
[...currNode.getNeighbors().keys()],
"| visited:",
[...visited.keys()]
);
for (const [neighborData, neighborNode] of currNode
.getNeighbors()
.entries()) {
console.log("currNeighbor:", neighborData);
if (neighborData === destination) {
return (found.res = true);
}
if (!visited.has(neighborData)) {
this.hasPathDFS(start, destination, neighborNode, visited, found);
}
}
return found.res;
}
addVertex(data) {
if (this.nodes.has(data)) {
return this.nodes.get(data);
}
const vertex = new Node(data);
this.nodes.set(data, vertex);
return vertex;
}
addEdge(source, destination) {
const sourceNode = this.addVertex(source);
const destinationNode = this.addVertex(destination);
sourceNode.addNeighbor(destinationNode);
if (this.edgeDirection === Graph.UNDIRECTED) {
destinationNode.addNeighbor(sourceNode);
}
return [sourceNode, destinationNode];
}
addEdges(edges) {
edges.forEach(([source, destination]) => this.addEdge(source, destination));
return this;
}
print() {
let str = [...this.nodes.values()]
.map(
(node) =>
`${node.data} => ${[...node.getNeighbors().keys()].join(", ")}`
)
.join("\n");
str = `${"_".repeat(100)}\n${str}\n${"_".repeat(100)}`;
console.log(str);
return str;
}
}
Graph.UNDIRECTED = Symbol("directed graph"); // two-way edges
Graph.DIRECTED = Symbol("undirected graph"); // one-way edges
const flightPaths = new Graph().addEdges(routes);
flightPaths.print();
console.log(flightPaths.hasPathDFSBroken("HEL", "EZE"));
// console.log(flightPaths.hasPathDFS("HEL", "EZE")); // working ver.
【问题讨论】:
-
请在问题中包含相关代码,不要只链接到外部代码。如果代码太大而无法发布,那么它肯定太大而不能成为一个好问题,所以请尝试创建一个minimal reproducible example。
标签: javascript node.js recursion graph depth-first-search