/** * Performs a traversal of the nodes reachable from {@code node}. 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. */ private static <N> boolean subgraphHasCycle( Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N node, @Nullable N previousNode) { NodeVisitState state = visitedNodes.get(node); if (state == NodeVisitState.COMPLETE) { return false; } if (state == NodeVisitState.PENDING) { return true; } visitedNodes.put(node, NodeVisitState.PENDING); for (N nextNode : graph.successors(node)) { if (canTraverseWithoutReusingEdge(graph, nextNode, previousNode) && subgraphHasCycle(graph, visitedNodes, nextNode, node)) { return true; } } visitedNodes.put(node, NodeVisitState.COMPLETE); return false; }
/** * Performs a traversal of the nodes reachable from {@code node}. 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. */ private static <N> boolean subgraphHasCycle( Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N node, @NullableDecl N previousNode) { NodeVisitState state = visitedNodes.get(node); if (state == NodeVisitState.COMPLETE) { return false; } if (state == NodeVisitState.PENDING) { return true; } visitedNodes.put(node, NodeVisitState.PENDING); for (N nextNode : graph.successors(node)) { if (canTraverseWithoutReusingEdge(graph, nextNode, previousNode) && subgraphHasCycle(graph, visitedNodes, nextNode, node)) { return true; } } visitedNodes.put(node, NodeVisitState.COMPLETE); return false; }
/** * Performs a traversal of the nodes reachable from {@code node}. 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. */ private static <N> boolean subgraphHasCycle( Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N node, @NullableDecl N previousNode) { NodeVisitState state = visitedNodes.get(node); if (state == NodeVisitState.COMPLETE) { return false; } if (state == NodeVisitState.PENDING) { return true; } visitedNodes.put(node, NodeVisitState.PENDING); for (N nextNode : graph.successors(node)) { if (canTraverseWithoutReusingEdge(graph, nextNode, previousNode) && subgraphHasCycle(graph, visitedNodes, nextNode, node)) { return true; } } visitedNodes.put(node, NodeVisitState.COMPLETE); return false; }
/** * Performs a traversal of the nodes reachable from {@code node}. 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. */ private static <N> boolean subgraphHasCycle( Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N node, @Nullable N previousNode) { NodeVisitState state = visitedNodes.get(node); if (state == NodeVisitState.COMPLETE) { return false; } if (state == NodeVisitState.PENDING) { return true; } visitedNodes.put(node, NodeVisitState.PENDING); for (N nextNode : graph.successors(node)) { if (canTraverseWithoutReusingEdge(graph, nextNode, previousNode) && subgraphHasCycle(graph, visitedNodes, nextNode, node)) { return true; } } visitedNodes.put(node, NodeVisitState.COMPLETE); return false; }
/** * Performs a traversal of the nodes reachable from {@code node}. 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. */ private static <N> boolean subgraphHasCycle( Graph<N> graph, Map<Object, NodeVisitState> visitedNodes, N node, @NullableDecl N previousNode) { NodeVisitState state = visitedNodes.get(node); if (state == NodeVisitState.COMPLETE) { return false; } if (state == NodeVisitState.PENDING) { return true; } visitedNodes.put(node, NodeVisitState.PENDING); for (N nextNode : graph.successors(node)) { if (canTraverseWithoutReusingEdge(graph, nextNode, previousNode) && subgraphHasCycle(graph, visitedNodes, nextNode, node)) { return true; } } visitedNodes.put(node, NodeVisitState.COMPLETE); return false; }