虽然关于这个主题有几个问题,但我需要一些更具体的建议。
我正在开发一个项目,我必须重命名一个实体。这意味着保存一个包含实体的旧名称和新名称的新对象。这就是软件的工作原理。
现在,我要做的是检查当有人试图重命名对象时是否尝试循环依赖。例如:
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的第一个循环。我缺少什么?
答案 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)