我正在尝试在JavaScript中为包含节点的以下网络编写路由/路径查找算法。每个节点都有规则来管理它是否可以作为入口点,出口点和/或被遍历。
如果选择了有效的入口点,我需要解决以下两个问题:
网络规则:
我将网络表示为一个对象数组,数组中的每个对象代表网络上的一个节点。
var network = [{
id: 'A',
canBeEntry: true,
ifEntryRouteIs: 'CW',
isExitIfRouteIs: 'N/A',
neighbourCW: ['B'],
neighbourCCW: ['H']
}, {
id: 'B',
canBeEntry: true,
ifEntryRouteIs: 'CW&CCW',
isExitIfRouteIs: 'CW',
neighbourCW: ['C'],
neighbourCCW: ['A']
},
.
.
.
{
id: 'H',
canBeEntry: false,
ifEntryRouteIs: 'N/A',
isExitIfRouteIs: 'N/A',
neighbourCW: ['A'],
neighbourCCW: ['G']
}];
描述有效进入/退出节点,转换和权重的图表如下:
我已经完成了一些或者研究与寻路和路由相关的算法,例如Dijkstra或A *搜索,但它们似乎是基于成本和权重,我不认为这适用于我的网络。
有没有人对如何在JavaScript中编写算法有任何想法或方法,首先确定出口点,然后是路线?
我试图在JavaScript中实现的内容就在这里 http://jsfiddle.net/mkov/dgGHm/
答案 0 :(得分:3)
如果我理解正确,你想要找到一个起始节点和方向,可能的出口和最短的路径。这应该工作:(必须稍微修改原始数据):
var validExitPoints =[];
var nodes=[];
var tree_path=[];
nodes.push({node:entryPoint});
visited[entryPoint]=true;
while(!nodes.length==0){
var node=network_obj[nodes[0].node];
nodes.shift();
if(canExit(node.id,dir)){
validExitPoints.push({node:node.id,path:''});
}
var neighbours=getNeighbours(node.id,dir);
for(var i=0;i<neighbours.length;i++){
if(visited[neighbours[i]]==false){
nodes.push({node:neighbours[i]});
visited[neighbours[i]]=true;
tree_path[neighbours[i]]=node.id;
}
}
}
这是主要代码,完整代码在这里:
http://jsfiddle.net/juvian/dgGHm/6/
我使用广度优先搜索,你可以在这里阅读更多信息:
答案 1 :(得分:2)
我发现您的网络数据结构有点复杂。你基本上有两个图(cw和cww)共享它们的顶点,但不是它们的边缘和出口和入口点。
下面的实现定义了单独的图形,并在图形网络中将它们连接起来。您可以使用Juvian建议的广度优先搜索为每个图创建最短路径列表。然后,您可以将这些列表组合到所有图表中。
下面的代码只是没有GUI和小提琴的路径搜索:
// Return an object that contains a path for each
// possible exit point
function find_exits(g, id, func) {
var visited = {};
var list = {};
var v = g[id];
var q = [[id, [id]]];
visited[id] = true;
if (v.exit) list[id] = [id];
while (q.length) {
var x = q.shift();
var path = x[1];
id = x[0];
v = g[id];
for (var i = 0; i < v.edge.length; i++) {
var next = v.edge[i];
if (next in visited) continue;
visited[next] = true;
if (g[next].exit) {
list[next] = path.concat([next]);
}
q.push([next, path.concat([next])]);
}
path.pop();
}
return list;
}
// Combine two exit lists, choose the shorter path if there
// is an exit in both lists
function union(a, b) {
var u = {};
for (var x in a) u[x] = a[x];
for (var x in b) {
if (x in a && a[x].length < b[x].length) continue;
u[x] = b[x];
}
return u;
}
var cw = {
A: {
entry: true,
edge: ['B']
},
B: {
entry: true,
exit: true,
edge: ['C']
},
C: {
entry: true,
edge: ['D']
},
D: {
edge: ['E', 'F']
},
E: {
exit: true
},
F: {
entry: true,
exit: true,
edge: ['G']
},
G: {
exit: true,
edge: ['H']
},
H: {
edge: ['A']
}
};
var ccw = {
A: {
edge: ['H']
},
B: {
entry: true,
edge: ['A']
},
C: {
exit: true,
edge: ['B']
},
D: {
entry: true,
edge: ['C']
},
E: {
entry: true,
edge: ['D']
},
F: {
entry: true,
exit: true,
edge: ['D']
},
G: {
entry: true,
edge: ['F']
},
H: {
edge: ['G']
}
};
// Housekeeping object for a network of several sub-graphs
var network = {
graphs: [cw, ccw],
traverse: function(func) {
for (var i = 0; i < this.graphs.length; i++) {
func(this.graphs[i]);
}
}
}
// Ensure that every vertex has edge, exit, entry
network.traverse(function(g) {
for (var id in g) {
var v = g[id];
if (!("edge" in v)) v.edge = [];
if (!("entry" in v)) v.entry = false;
if (!("exit" in v)) v.exit = false;
}
});
// Actual path-seeking
var start = 'B';
var exits = {};
network.traverse(function(g) {
if (g[start].entry) {
exits = union(exits, find_exits(g, start));
}
});
console.log(exits);
这个例子没有显示实际路径的图形,但我认为可以轻松添加。