如何检测有向图是否是循环的?

时间:2010-03-26 17:22:09

标签: graph breadth-first-search cyclic

我们如何检测有向图是否是循环的?我认为使用广度优先搜索,但我不确定。有任何想法吗?

6 个答案:

答案 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”标志的节点,你知道有一个循环。

如果无法修改图形以包含“已访问”位,则可以使用一组节点指针代替。要将节点标记为已访问,请在集合中放置指向它的指针。如果指针已经在集合中,则有一个循环。

相关问题