检测未连接图中的周期

时间:2015-10-01 15:51:22

标签: java graph dependencies

虽然关于这个主题有几个问题,但我需要一些更具体的建议。

我正在开发一个项目,我必须重命名一个实体。这意味着保存一个包含实体的旧名称和新名称的新对象。这就是软件的工作原理。

现在,我要做的是检查当有人试图重命名对象时是否尝试循环依赖。例如:

A -> B
B -> C
C -> A

当有人试图将C重命名为A时,应该发出信号。

我不知道如何解决这个问题。我的想法是创建一个具有边[A,B],[B,C],[C,A]的有向图,并应用一些循环检测算法来找到循环依赖(Tarjan或其他)。

考虑到图表不会连接,这会有效吗?可以有上述例子然后:

E -> F
H -> J
X -> Y

我最终会遇到许多未连接的边缘和几个周期。我应该首先找到较小的连接图并在每个图上应用任何算法,或者是否有可能只添加构建大图并在其上应用算法?

检测我的示例的循环依赖项的最快和推荐的方法是什么?

谢谢!

更新 我提出了以下dfs方法:

void DFS(int root, boolean[] visited){
        onStack = new boolean[N];
        edgeTo = new int[N];

        visited[root]=true;
        onStack[root] = true;

        for (int i=0; i<N; ++i){
            if (G[root][i]){ 
                if(!visited[i]){
                   DFS(i,visited);
                } else if (onStack[i]){
                   System.out.printf("%nCycle %n");
                }
          } else {
              System.out.printf("%nG[" + root + "][" + i + "] is not an edge%n");
          }

          onStack[root] = false;
        }

    }

并将其称为:

void DFS()
    {
        boolean[] visited =new boolean[N]; 
        int numComponets=0;

        // do the DFS from each node not already visited
        for (int i=0; i<N; ++i)
            if (!visited[i] && cycle == null)
            {
                ++numComponets;             
                DFS(i,visited);
            } 
    }

它成功找到连接的组件,但不识别任何循环,只有当我删除G [root] [i]条件时,这将是从0到0的第一个循环。我缺少什么?

2 个答案:

答案 0 :(得分:0)

如果我正确理解了您的问题,当有人将实体名称更改为该实体以前使用的名称时,您将只获得循环依赖。

考虑到这一点,为什么不只是创建一个包含实体所有名称的集合,以及每当用户尝试更改名称时检查名称是否在您的集合中。如果是,那么这将创建循环依赖项,如果它不在您的集合中,则将其添加到集合中并允许名称更改操作继续。

HashSet这样的集合对于这种方法很有用,因为它为元素查找提供了平均O(1)时间复杂度。

答案 1 :(得分:0)

您可以简单地维护所有节点的集合S。然后从该集合中获取一个节点,在该节点上运行dfs / bfs,检查后沿(如果是,则表示您有一个循环)。对于您访问的每个节点,从集合S中删除该节点。完成dfs / bfs后,检查S是否为空。如果是这样,那么你就知道没有周期。否则,从S获取节点,并在该节点上运行dfs / bfs。运行时应为O(n),其中n是节点数。

伪代码:

S = set(all nodes)
while len(S) > 0:
    node = S.pop()
    stack = [node]
    visited = set()
    while len(stack) > 0:
        node = stack.pop()
        visited.add(node)
        S.remove(node)
        for each neighbor of node in your graph:
            if neighbor in visited:
                # you know you have a cycle

            else:
                stack.append(node)