MCPcopy
hub / github.com/google/guava / subgraphHasCycle

Method subgraphHasCycle

guava/src/com/google/common/graph/Graphs.java:101–140  ·  view source on GitHub ↗

Performs a traversal of the nodes reachable from {@code startNode}. If we ever reach a node we've already visited (following only outgoing edges and without reusing edges), we know there's a cycle in the graph.

(
      Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N startNode)

Source from the content-addressed store, hash-verified

99 * there's a cycle in the graph.
100 */
101 private static <N> boolean subgraphHasCycle(
102 Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N startNode) {
103 Deque<NodeAndRemainingSuccessors<N>> stack = new ArrayDeque<>();
104 stack.addLast(new NodeAndRemainingSuccessors<>(startNode));
105
106 while (!stack.isEmpty()) {
107 // To peek at the top two items, we need to temporarily remove one.
108 NodeAndRemainingSuccessors<N> top = stack.removeLast();
109 NodeAndRemainingSuccessors<N> prev = stack.peekLast();
110 stack.addLast(top);
111
112 N node = top.node;
113 N previousNode = prev == null ? null : prev.node;
114 if (top.remainingSuccessors == null) {
115 NodeVisitState state = visitedNodes.get(node);
116 if (state == NodeVisitState.COMPLETE) {
117 stack.removeLast();
118 continue;
119 }
120 if (state == NodeVisitState.PENDING) {
121 return true;
122 }
123
124 visitedNodes.put(node, NodeVisitState.PENDING);
125 top.remainingSuccessors = new ArrayDeque<>(graph.successors(node));
126 }
127
128 if (!top.remainingSuccessors.isEmpty()) {
129 N nextNode = top.remainingSuccessors.remove();
130 if (canTraverseWithoutReusingEdge(graph, nextNode, previousNode)) {
131 stack.addLast(new NodeAndRemainingSuccessors<>(nextNode));
132 continue;
133 }
134 }
135
136 stack.removeLast();
137 visitedNodes.put(node, NodeVisitState.COMPLETE);
138 }
139 return false;
140 }
141
142 private static final class NodeAndRemainingSuccessors<N> {
143 final N node;

Callers 1

hasCycleMethod · 0.95

Calls 9

isEmptyMethod · 0.65
getMethod · 0.65
putMethod · 0.65
successorsMethod · 0.65
removeMethod · 0.65
addLastMethod · 0.45
removeLastMethod · 0.45
peekLastMethod · 0.45

Tested by

no test coverage detected