我们如何检测有向图是否是循环的?我认为使用广度优先搜索,但我不确定。有任何想法吗?
答案 0 :(得分:16)
我认为,您真正需要的是一种拓扑排序算法,如下所述:
http://en.wikipedia.org/wiki/Topological_sorting
如果有向图有一个周期,那么算法就会失败。
到目前为止我看到的评论/回复似乎忽略了这样一个事实:在定向图中,可能有多种方法从节点X到节点Y而没有图中的任何(定向)循环。
答案 1 :(得分:13)
通常使用深度优先搜索。 我不知道BFS是否适用。
在DFS中,生成树按访问顺序构建。如果访问树中节点的祖先(即创建了后边缘),则我们检测到一个循环。
有关更详细的说明,请参阅http://www.cs.nyu.edu/courses/summer04/G22.1170-001/6a-Graphs-More.pdf。
答案 2 :(得分:2)
使用DFS搜索是否有任何路径是循环的
class Node<T> { T value; List<Node<T>> adjacent; }
class Graph<T>{
List<Node<T>> nodes;
public boolean isCyclicRec()
{
for (Node<T> node : nodes)
{
Set<Node<T>> initPath = new HashSet<>();
if (isCyclicRec(node, initPath))
{
return true;
}
}
return false;
}
private boolean isCyclicRec(Node<T> currNode, Set<Node<T>> path)
{
if (path.contains(currNode))
{
return true;
}
else
{
path.add(currNode);
for (Node<T> node : currNode.adjacent)
{
if (isCyclicRec(node, path))
{
return true;
}
else
{
path.remove(node);
}
}
}
return false;
}
答案 3 :(得分:1)
的方法:1个
一个级别如何没有分配来检测一个循环。例如:考虑下面的图表。 A->(B,C)B-> D D->(E,F)E,F->(G)E-> D当您执行DFS开始为节点分配级别no时你访问(根A = 0)。节点的级别号=父级+ 1。所以A = 0,B = 1,D = 2,F = 3,G = 4然后,递归达到D,所以E = 3。不要标记G的等级(G已经没有分配比E更重要的等级)现在E也有一个D的边缘。所以等级化会说D应该得到4的等级。但是D已经分配了“较低等级”因此,每当您尝试为已经设置了较低级别编号的DFS分配级别编号时,您知道有向图有一个循环..
approach2:
使用3种颜色。白色,灰色,黑色。颜色只有白色节点,当你向下移动DFS时白色节点变为灰色,当递归展开时颜色灰色节点变为黑色(所有子节点都被处理)。如果不是所有的孩子都处理了,你就会遇到一个循环的灰色节点。
例如:全部白色从上面的直接图开始。
颜色A,B,D,F,G为白灰色。 G是叶子所以所有孩子都处理颜色从灰色到黑色。递归到F(所有处理的孩子)将它染成黑色。现在你到达D,D有未经处理的孩子,所以颜色E灰色,G已经是黑色,所以不要再往下走了。 E也有边缘到D,所以当仍然处理D(D仍为灰色)时,你会发现边缘回到D(灰色节点),检测到一个周期。
答案 4 :(得分:0)
在给定图表上测试拓扑排序将引导您找到解决方案。如果topsort的算法,即边缘应始终以一种方式指向失败,则表示图形包含循环。
答案 5 :(得分:-1)
另一个简单的解决方案是标记和扫描方法。基本上,对于树中的每个节点,您将其标记为“已访问”,然后转移到它的子节点。如果你看到一个设置了“visted”标志的节点,你知道有一个循环。
如果无法修改图形以包含“已访问”位,则可以使用一组节点指针代替。要将节点标记为已访问,请在集合中放置指向它的指针。如果指针已经在集合中,则有一个循环。