用Javascript实现有向图的广度优先搜索

刚好遇到一个需求,对于一个有向图,指定一个节点 i 作为起点,输出从 i 出发,可以到达的所有节点,也就是图中以 i 作为起点的子连通片,思考了一下,可以用以前学的广度优先搜索解决。

一、有向图的存储

我们用一个邻接矩阵(二维数组)存储有向图的信息,对于一个矩阵graph,若graph[i][j] = true,则表示存在一条由节点 i 到 j 的边。

// 使用d3读取json文件
d3.json("test.json", function(error, graph) {
// 构造邻接矩阵
var graph_array = new Array();
graph.links.forEach(function(d){
if(!graph_array[d.source])
{
graph_array[d.source]= new Array();
}
graph_array[d.source][d.target] = true;
});
}

二、广度优先搜索(Breadth First Search)

步骤:

(0)创建一个队列存储经过的节点,把当前节点初始化为 i ,并将其入队(push)

(1)进行一次出队操作(pop),得到队首的节点 j(此时应把j记录下来,作为返回结果),遍历以 j 为起点的边,把这些边的终点节点依次入队

(2)判断队列是否为空,若是,则返回结果;若否,则跳回第一步继续执行。

算法的时间复杂度为O(n²)

具体代码如下:

function breadth_first_search(graph_array, root)
{
var ret_nodes = {}; // 用于存储经过的节点
var queue = [];
queue.push(root); do
{
var current_node = queue.shift();
ret_nodes[current_node] = true; for(var i = 0; graph_array[current_node] && i < graph_array[current_node].length; i++)
{
if(graph_array[current_node][i])
{
queue.push(i);
}
}
}while(queue.length !== 0); return ret_nodes;
}
05-11 22:14