我应该如何在有向图中找到循环并列出形成循环的节点?

时间:2017-08-16 14:37:46

标签: javascript algorithm data-structures graph

我有javascript中的对象数组我试图绘制有向图我应该如何找到它是否包含循环如果包含什么是形成循环的元素 图形没有强连接,节点可以像“f”

那样被隔离
 array = {};
//operations   parents
    array[a] = [b,c]
    array[b] = [d,c]
    array[e] = [a,b]
    array[d] = [e]
    array[f] = []

considering the above data- assume keys as child and values as parents made a directed graph which looks like this

我想找到这样的操作之间的循环,就像我们从e-d-b-e循环一样? 我该如何找到这个循环?我正在使用javascript。

4 个答案:

答案 0 :(得分:1)

这是一个BFS解决方案,它将找到一个周期(如果有的话),它将是(最短的)一个周期。

function getCycle(graph) {
    // Copy the graph, converting all node references to String
    graph = Object.assign(...Object.keys(graph).map( node =>
                ({ [node]: graph[node].map(String) }) 
    ));

    let queue = Object.keys(graph).map( node => [node] );
    while (queue.length) {
        const batch = [];
        for (const path of queue) {
            const parents = graph[path[0]] || [];
            for (const node of parents) {
                if (node === path[path.length-1]) return [node, ...path];
                batch.push([node, ...path]);
            }
        }
        queue = batch;
    }
}

// First example
var graph = {
    a: ['b', 'c'],
    b: ['d', 'c'],
    e: ['a', 'b'],
    d: ['e']
};
var result = getCycle(graph);
console.log(result);

// Second example (numeric node references)
var graph = {
    0: [4],
    1: [4,0],
    2: [0,1],
    3: [1],
    4: [3]
};
var result = getCycle(graph);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

注意:如果使用数字引用定义图形,则需要进行类型转换,因为对象属性始终是字符串类型。我们可以使用==代替===,但输出仍然是字符串和数字的混合;我认为首先将每个节点引用转换为字符串会更好。

答案 1 :(得分:0)

深度优先搜索。如果DFS找到指向当前节点已发现的祖先的边,则该图包含一个循环。

答案 2 :(得分:0)

因此,我评论说,你需要基本遍历整个图形并保持一个访问过的数组来跟踪你到目前为止访问过的节点,如果你到达任何已经访问过的节点,那么在提供的节点中就存在一个循环有向图。

为了让您的工作更轻松,这是一个正在运行的代码,您可以将其用作参考来构建您的算法。

稍微改进了我的答案,遍历所有节点,以便它覆盖一些无法到达的路径。谢谢大家:))

array = {};

/*
Assuming 
a = 0
b=  1
c = 2
d = 3
e = 4
*/

// Here I am forming an adjacency list of directed nodes based on the diagram
array[0] = [4];
array[1] = [4,0];
array[2] = [0,1];
array[4] = [3];
array[3] = [1];
visited = {};
visited[0] = 0;
visited[1] = 0;
visited[2] = 0;
visited[3] = 0;
visited[4] = 0;

list_for_cycle_nodes = [];

for(var node = 0; node<5; node++) {
   if (dfs(node)) {
    for (var index = 0; index < list_for_cycle_nodes.length; index++) {
      console.log(list_for_cycle_nodes[index]+" ");
    }
    console.log('There is a cycle');
  } else {
    console.log('Yipee, there is no cycle');
  } 
}

function dfs(s) {
  if(visited[s] == 1) {
    return true;
  }
  list_for_cycle_nodes.push(s);
  visited[s] = 1;
  var flag = false;
  if(array[s].length <= 0) {
    return false;
  }
  for(var index = 0; index<array[s].length; index++) {
    flag = flag | dfs(array[s][index]);
    if(flag) {
      return true;
    }
  }
  return flag;
}

希望这有帮助!

答案 3 :(得分:0)

在参考有关@zenwraigts解决方案的评论后,我推断这是Strongly Connected Components的问题。你可以找到一个好的教程here,你可以找到javascript实现herehere

这是SCC的问题怎么样?

所有顶点形成一个循环的强连通组件,问题减少到找到所有SCC并打印它们