[英]Java Detecting a cyclic directed Graph
I am currently trying to write a procedure to check whether a directed graph is cyclic or not . 我目前正在尝试编写一个过程来检查有向图是否是循环的 。 I am not sure what i did wrong (it may be well possible that I did everything wrong, so please StackOverflow, show me my stupidity!).
我不确定我做错了什么(我很可能做错了所以所以请StackOverflow,告诉我我的愚蠢!)。 I'd be thankful for any kind of help as I've come to the point where I don't know what could be the problem.
我会感谢任何帮助,因为我已经到了不知道可能出现什么问题的地步。
The input is an adjacency list such as: 输入是一个邻接列表,例如:
0: 2 4
1: 2 4
2: 3 4
3: 4
4: 0 1 2 3
(0 directs to 2 and 4; 1 directs to 2 and 4 and so on...) (0指向2和4; 1指向2和4,依此类推......)
The idea is that I check whether the node I am checking is 'grey' (partially explored) or not. 我的想法是检查我正在检查的节点是否为“灰色”(部分探索)。 If it is, it must be a back edge and thus a cyclic graph.
如果是,则它必须是后边缘,因此是循环图。 Black edges are always explored or cross-edges, so this shouldn't trigger a cyclic message.
始终探索黑色边缘或交叉边缘,因此不应触发循环消息。 I am aiming to do depth first search
我的目标是深度搜索
If A-->B and B-->A, this should not trigger a message about cyclic (but A--> B, B-->C, C-->A should). 如果A - > B和B - > A,则不应触发有关循环的消息(但A - > B,B - > C,C - > A应该)。
hasCycle calls hasCycleInSubgraph which calls itself recursively through the Adjency List of the Graph. hasCycle调用hasCycleInSubgraph,它通过图的Adjency List递归调用自身。
class qs {
private ArrayList<Integer>[] adjList;
private Stack<Integer> stack;
private ArrayList<Integer> whiteHat;
private ArrayList<Integer> greyHat;
private ArrayList<Integer> blackHat;
public qs(ArrayList<Integer>[] graph) {
this.adjList = graph;
this.stack = new Stack();
this.whiteHat = new ArrayList<Integer>();
this.greyHat = new ArrayList<Integer>();
this.blackHat = new ArrayList<Integer>();
for (Integer h = 0; h < adjList.length; h++) {
whiteHat.add(h);
}
}
public boolean hasCycle() {
for (Integer i = 0; i < adjList.length; i++) {
// System.out.print("Local root is: ");
// System.out.println(i);
whiteHat.remove(i);
greyHat.add(i);
if (hasCycleInSubgraph(i) == true) {
return true;
}
greyHat.remove(i);
blackHat.add(i);
}
return false;
}
public boolean hasCycleInSubgraph(Integer inp) {
if (blackHat.contains(inp)) {
return false;
}
for (Integer branch : adjList[inp]) {
// System.out.print("Adj is: ");
// System.out.println(branch);
if ( greyHat.contains(branch) && !inp.equals(branch) ) {
return true;
}
whiteHat.remove(branch);
greyHat.add(branch);
if ( hasCycleInSubgraph(branch) == true ) {
return true;
}
greyHat.remove(branch);
blackHat.add(branch);
}
return false;
}
}
You are over-complicating it: a cycle can be detected via a depth-first search: from any given node, walk to each of the connected nodes; 你过度复杂了:可以通过深度优先搜索来检测循环:从任何给定节点,走到每个连接的节点; if you arrive back at an already-visited node, you've got a cycle.
如果你回到已经访问过的节点,你就有了一个周期。
class qs {
private final ArrayList<Integer>[] graph;
qs(ArrayList<Integer>[] graph) {
this.graph = graph;
}
boolean hasCycle() {
List<Integer> visited = new ArrayList<>();
for (int i = 0; i < graph.length; ++i) {
if (hasCycle(i, visited)) {
return true;
}
}
}
private boolean hasCycle(int node, List<Integer> visited) {
if (visited.contains(node)) {
return true;
}
visited.add(node);
for (Integer nextNode : graph[node]) {
if (hasCycle(nextNode, visited)) {
return true;
}
}
visited.remove(visited.length() - 1);
return false;
}
}
If you want to detect cycles longer than a given length, just check the depth of the recursion: 如果要检测超过给定长度的周期,只需检查递归的深度:
if (visited.contains(node) && visited.size() > 2) {
Note that this does not require any state to be kept, aside from what is in the stack. 请注意,除了堆栈中的内容之外,这不需要保留任何状态。 Relying upon mutable state makes the code thread-unsafe (eg that two threads calling
hasCycle
at the same time would interfer with each other), and so should be avoided - even if you don't expect the code to be used in a multi-threaded way now, it avoids problems down the line. 依赖于可变状态会使代码线程不安全(例如,同时调用
hasCycle
两个线程会相互干扰),因此应该避免 - 即使您不希望代码在多个中使用现在采用线程方式,它可以避免出现问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.