JavaScript中多向网络的路由或寻路算法

时间:2014-04-17 03:58:30

标签: javascript algorithm networking tree path-finding

我正在尝试在JavaScript中为包含节点的以下网络编写路由/路径查找算法。每个节点都有规则来管理它是否可以作为入口点,出口点和/或被遍历。

Routable Network

如果选择了有效的入口点,我需要解决以下两个问题:

  1. 网络的有效和可用退出点
  2. 确定并选择有效的出口点后,最佳路径是什么(需要遍历的节点)
  3. 网络规则:

    1. 您只能输入带入口点的节点,即节点A,B C,D,E,F,G
    2. 您只能退出带退出点的节点,即节点B,C,E,F,G
    3. 行程的方向由入口节点决定 - 这决定了你可以行进和退出的方向。 。例如。通过节点A进入时顺时针方向行驶和退出
    4. 进入网络后,您无法更改方向。
    5. 我将网络表示为一个对象数组,数组中的每个对象代表网络上的一个节点。

          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']
                          }];
      

      描述有效进入/退出节点,转换和权重的图表如下:

      Network Graphs

      我已经完成了一些或者研究与寻路和路由相关的算法,例如Dijkstra或A *搜索,但它们似乎是基于成本和权重,我不认为这适用于我的网络。

      有没有人对如何在JavaScript中编写算法有任何想法或方法,首先确定出口点,然后是路线?

      我试图在JavaScript中实现的内容就在这里 http://jsfiddle.net/mkov/dgGHm/

2 个答案:

答案 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/

我使用广度优先搜索,你可以在这里阅读更多信息:

http://en.wikipedia.org/wiki/Breadth-first_search

答案 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);

这个例子没有显示实际路径的图形,但我认为可以轻松添加。