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)
| 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; |
no test coverage detected