Javascript - 图形遍历 - 返回最短路径

时间:2016-06-25 23:53:45

标签: javascript graph-theory graph-algorithm graph-traversal

我想遍历一个图表。我有两种结构:

var Node = function(name) {  
    this.edge_list = [];
    this.name = name;
};

var Graph = function() {  
    this.node_list = [];
};

边缘被添加到节点,如下所示:

Node.prototype.addEdge = function(end, distance) {  
    this.edge_list.push({end, distance});
};

图表可能如下所示:

start:
[ Object { end: '1', distance: 13 },
  Object { end: '2', distance: 14 } ]
1:
[ Object { end: 'start', distance: 13 },
  Object { end: '3', distance: 2 } ]
2:
[ Object { end: 'start', distance: 14 },
  Object { end: '3', distance: 1 } ]
3:
[ Object { end: '1', distance: 2 },
  Object { end: '2', distance: 1 },
  Object { end: 'end', distance: 10 } ]
end:
[ Object { end: '3', distance: 10 } ]

我要做的是创建一个函数,它将返回从sourcetarget的最短距离/路径。

我目前正在测试https://repl.it/C6Fh

1 个答案:

答案 0 :(得分:0)

如果距离是正的,那么dijkstra就是你要走的路。但是,一个非常简单的算法是:

  • 标记每个节点具有无限距离,源节点的距离为0。
  • 从源代码开始在图表上执行广度优先遍历:
    • 如果当前边缘导致较小的距离,则更新节点的距离
    • 将该节点添加到队列的末尾

以下是我的快速解决方案,用于存储Node类的距离和先前节点。

您将在节点本身找到最小距离,例如dstNode.distance。 对于路径,只需从dstNode追溯并按照prev链接。

function shortest_path(g, src, dst) {
    var get_node = function(n) {
        for (var i = 0; i < g.node_list.length; i++) {
            if (g.node_list[i].name == n) {
                return g.node_list[i];
            }
        }
        return null;
    }

    var srcNode = get_node(src);
    var dstNode = get_node(dst);
    for(var i = 0; i < g.node_list.length; i++) {
        // think of as infinity (currently assumed to be unreachable)
        g.node_list[i].distance = 2147483647;
        g.node_list[i].prev = null;
    }
    srcNode.distance = 0; // src node is of distance zero from itself

    q = [srcNode]; // we will breadth-first traverse the graph
    while (q.length > 0) {
        var cur = q[0];
        q.shift();
        for (var i = 0; i < cur.edge_list.length; i++) {
            n = get_node(cur.edge_list[i].end);
            // here we are looping through neighbors of cur
            // to see if a smaller distance exists
            if (n.distance > cur.distance + cur.edge_list[i].distance) {
                n.distance = cur.distance + cur.edge_list[i].distance;
                n.prev = cur;
                q.push(n);
            }
        }
    }
}