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

发布于 2024-08-26 08:00:51 字数 47 浏览 8 评论 0原文

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

How can we detect if a directed graph is cyclic? I thought using breadth first search, but I'm not sure. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夏夜暖风 2024-09-02 08:00:51

我相信,您真正需要的是一种拓扑排序算法,如下所述:

http://en。 wikipedia.org/wiki/Topological_sorting

如果有向图有环,则算法将失败。

到目前为止我看到的评论/回复似乎忽略了这样一个事实:在有向图中,可能有不止一种方法可以从节点 X 到节点 Y,而没有任何(有向) ) 图中的循环。

What you really need, I believe, is a topological sorting algorithm like the one described here:

http://en.wikipedia.org/wiki/Topological_sorting

If the directed graph has a cycle then the algorithm will fail.

The comments/replies that I've seen so far seem to be missing the fact that in a directed graph there may be more than one way to get from node X to node Y without there being any (directed) cycles in the graph.

浪漫人生路 2024-09-02 08:00:51

通常使用深度优先搜索来代替。 我不知道 BFS 是否容易应用。

DFS,按照访问顺序构建生成树。如果访问了树中节点的祖先(即创建了后边),则我们检测到循环。

请参阅http://www.cs。 nyu.edu/courses/summer04/G22.1170-001/6a-Graphs-More.pdf 了解更详细的说明。

Usually depth-first search is used instead. I don't know if BFS is applicable easily.

In DFS, a spanning tree is built in order of visiting. If a the ancestor of a node in the tree is visited (i.e. a back-edge is created), then we detect a cycle.

See http://www.cs.nyu.edu/courses/summer04/G22.1170-001/6a-Graphs-More.pdf for a more detailed explanation.

北城挽邺 2024-09-02 08:00:51

使用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;
  }

Use DFS to search if any path is cyclic

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;
  }
古镇旧梦 2024-09-02 08:00:51

方法: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 已经分配了“较低级别”到它的2。因此,任何时候当你在执行已经设置了较低级别编号的DFS时尝试为节点分配级别编号时,你都知道有向图有一个循环..

方法2:
使用 3 种颜色。白色、灰色、黑色。仅将白色节点着色为白色节点,当您沿着 DFS 向下时将白色节点着色为灰色,当递归展开时将灰色节点着色为黑色(所有子节点均已处理)。如果尚未处理所有子节点并且您遇到灰色节点,那就是一个循环。
例如:在上面的直接图中开始全白色。
颜色 A、B、D、F、G 为白灰色。 G 是叶子,所以所有孩子都将其颜色处理为灰色到黑色。递归展开到 F(所有子进程都已处理),将其涂成黑色。现在你到达D,D有未处理的孩子,所以E颜色为灰色,G已经颜色为黑色,所以不要再往下走。 E 也有到 D 的边,所以当仍在处理 D(D 仍然是灰色)时,您会发现一条回到 D(灰色节点)的边,检测到循环。

approach:1
how about a level no assignment to detect a cycle. eg: consider the graph below. A->(B,C) B->D D->(E,F) E,F->(G) E->D As you perform a DFS start assigning a level no to the node you visit (root A=0). level no of node = parent+1. So A=0, B=1, D=2, F=3, G=4 then, recursion reaches D, so E=3. Dont mark level for G (G already a level no assigned which is grater than E) Now E also has an edge to D. So levelization would say D should get a level no of 4. But D already has a "lower level" assigned to it of 2. Thus any time you attempt to assign a level number to a node while doing DFS that already has a lower level number set to it, you know the directed graph has a cycle..

approach2:
use 3 colors. white, gray, black. color only white nodes, white nodes to gray as you go down the DFS, color gray nodes to black when recursion unfolds (all children are processed). if not all children yet processed and you hit a gray node thats a cycle.
eg: all white to begin in above direct graph.
color A, B, D, F,G are colored white-gray. G is leaf so all children processed color it gray to black. recursion unfolds to F(all children processed) color it black. now you reach D, D has unprocessed children, so color E gray, G already colored black so dont go further down. E also has edge to D, so while still processing D (D still gray), you find an edge back to D(a gray node), a cycle is detected.

天涯沦落人 2024-09-02 08:00:51

对给定图进行拓扑排序测试将引导您找到解决方案。如果顶排序算法(即边应始终以一种方式定向)失败,则意味着该图包含循环。

Testing for Topological sort over the given graph will lead you to the solution. If the algorithm for topsort, i.e the edges should always be directed in one way fails, then it means that the graph contains cycles.

抚笙 2024-09-02 08:00:51

另一个简单的解决方案是标记和清除方法。基本上,对于树中的每个节点,您将其标记为“已访问”,然后继续处理它的子节点。如果您看到设置了“visted”标志的节点,您就知道存在循环。

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

Another simple solution would be a mark-and-sweep approach. Basically, for each node in tree you flag it as "visited" and then move on to it's children. If you ever see a node with the "visted" flag set, you know there's a cycle.

If modifying the graph to include a "visited" bit isn't possible, a set of node pointers can be used instead. To flag a node as visited, you place a pointer to it in the set. If the pointer is already in the set, there's a cycle.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文