如果选择F到C,我的程序输出应该如下所示。
F,D,C费用:2
F,D,E,C成本:4
F,D,B,A,C成本:5
F,D,G,B,A,C成本:7
但是,我一直得到像这样的输出
F,D,C费用:2
我试图获得其他输出,但程序永远不会有效,这就像我得到的那样接近。
我错过了什么?
function calculateNow() {
var g = new Graph();
calculate();
function Graph() {
this.edges = {};
this.addNode = function(label) {
this.edges[label] = {};
};
this.addEdge = function(from, to, cost) {
this.edges[from][to] = cost;
this.edges[to][from] = cost;
};
this.calculatePaths = function(from, to, cost, paths) {
if (g.edges[from][to]) {
cost = g.edges[from][to];
paths = paths.concat("," + to);
g.displayPath(paths, cost);
} else {
next = getNextEdge(from);
cost = cost + g.edges[from][next];
paths = paths.concat("," + next);
g.displayPath(paths, cost);
if (next !== to) {
g.calculatePaths(next, to, cost, paths);
}
}
};
function getNextEdge(from) {
var res, cost = 999;
if (g.edges[from]['A']) {
cost = g.edges[from]['A'];
res = 'A';
}
if (g.edges[from]['B'] && g.edges[from]['B'] <= cost) {
cost = g.edges[from]['B'];
res = 'B';
}
if (g.edges[from]['C'] && g.edges[from]['C'] <= cost) {
cost = g.edges[from]['C'];
res = 'C';
}
if (g.edges[from]['D'] && g.edges[from]['D'] <= cost) {
cost = g.edges[from]['D'];
res = 'D';
}
if (g.edges[from]['E'] && g.edges[from]['E'] <= cost) {
cost = g.edges[from]['E'];
res = 'E';
}
if (g.edges[from]['F'] && g.edges[from]['F'] <= cost) {
cost = g.edges[from]['F'];
res = 'F';
}
if (g.edges[from]['G'] && g.edges[from]['G'] <= cost) {
cost = g.edges[from]['G'];
res = 'G';
}
return res;
}
this.displayPath = function(path, cost) {
var res = document.getElementById('result');
res.innerHTML = path + " Cost: " + (cost*2);
};
}
function calculate() {
var from = document.getElementById('from').value;
var to = document.getElementById('to').value;
g.addNode('A');
g.addNode('B');
g.addNode('C');
g.addNode('D');
g.addNode('E');
g.addNode('F');
g.addNode('G');
g.addEdge('A', 'B', 2);
g.addEdge('A', 'C', 1);
g.addEdge('B', 'D', 1);
g.addEdge('B', 'G', 1);
g.addEdge('C', 'D', 1);
g.addEdge('C', 'E', 1);
g.addEdge('D', 'E', 2);
g.addEdge('D', 'F', 1);
g.addEdge('D', 'G', 2);
g.calculatePaths(from, to, 0, "" + from);
}
}
Select two nodes:
<br />From
<select id="from">
<option value='A'>A</option>
<option value='B'>B</option>
<option value='C'>C</option>
<option value='D'>D</option>
<option value='E'>E</option>
<option value='F' selected>F</option>
<option value='G'>G</option>
</select>To
<select id="to">
<option value='A'>A</option>
<option value='B'>B</option>
<option value='C' selected>C</option>
<option value='D'>D</option>
<option value='E'>E</option>
<option value='F'>F</option>
<option value='G'>G</option>
</select>
<input type="button" onclick="calculateNow();" value="Calculate" />
<br/>
<br/><span id="result" />
答案 0 :(得分:1)
代码中的逻辑问题是使用getNextEdge
。似乎在每个节点上,您只挑选一条边进行探索,但根据您的预期输出,您似乎真的想要探索每个边缘。
这是我对代码的看法,将getNextEdge
的使用替换为离开该节点的所有边缘的循环:
function Graph() {
this.edges = {};
this.addNode = function(label) {
this.edges[label] = {};
};
this.addEdge = function(from, to, cost) {
this.edges[from][to] = cost;
this.edges[to][from] = cost;
};
this.calculatePaths = function(from, to, cost, path) {
// Recursion base case: we're already at the destination node
if (from === to) {
this.displayPath(path, cost);
} else {
// Capture this, since it will be reassigned in the loop
var that = this;
Object.keys(this.edges[from]).forEach(function (next) {
// Don't visit this node again if we already have
for (var i = 0; i < path.length; i++) {
if (path[i] === next) {
return;
}
}
// Recurse
that.calculatePaths(next, to, cost + that.edges[from][next], path.concat([next]));
});
}
};
this.displayPath = function(path, cost) {
console.log(path.join(", ") + ' Cost: ' + cost);
};
}
function calculate(from, to) {
var g = new Graph();
g.addNode('A');
g.addNode('B');
g.addNode('C');
g.addNode('D');
g.addNode('E');
g.addNode('F');
g.addNode('G');
g.addEdge('A', 'B', 2);
g.addEdge('A', 'C', 1);
g.addEdge('B', 'D', 1);
g.addEdge('B', 'G', 1);
g.addEdge('C', 'D', 1);
g.addEdge('C', 'E', 1);
g.addEdge('D', 'E', 2);
g.addEdge('D', 'F', 1);
g.addEdge('D', 'G', 2);
g.calculatePaths(from, to, 0, [from]);
}
calculate('F', 'C');
&#13;