下面的代码可以正常运行,除非它通过非循环图运行。它将非循环图标记为循环图,我不明白为什么。
@Override
public boolean isCyclic(DirectedGraph<T> graph) {
List<Node<T>> visitedNodes = new ArrayList<>();
int cycles = 0;
for (Node<T> node : graph) {
if (recNodeCycleCheck(node, visitedNodes)) {
cycles++;
}
visitedNodes = new ArrayList<>();
}
return cycles > 0;
}
private boolean recNodeCycleCheck(Node<T> node, List<Node<T>> visitedNodes) {
if (visitedNodes.contains(node)) {
return true;
}
visitedNodes.add(node);
for (Iterator<Node<T>> it = node.succsOf(); it.hasNext();) {
Node<T> currentNode = it.next();
if (visitedNodes.contains(currentNode)) {
return true;
}
if (recNodeCycleCheck(currentNode, visitedNodes)) {
return true;
}
}
return false;
}
我试图尽可能清楚地命名代码,以便于阅读。第一个方法isCyclic()接收一个图,并针对图中的每个节点检查其相邻列表以及该列表中节点的后继对象。如果它们在任何时候都指向已访问的节点,则该图是循环的。
这似乎对除无环图之外的所有图都适用。
有什么想法吗?
答案 0 :(得分:0)
您的逻辑很可能没有考虑以下非循环图的情况:
//A, B and C are the nodes in the graph
A -> B // Edge between A and B
B -> C // Edge between B and C
A -> C // Edge between A and C
在这种情况下,您的算法所执行的操作-以A开头,访问B和C。然后转到A的下一个继承者(即C),然后查看它是否已被访问,并返回true。