|
| 1 | +""" |
| 2 | +Given a directed graph, check whether it contains a cycle. |
| 3 | +
|
| 4 | +Real-life scenario: deadlock detection in a system. Processes may be |
| 5 | +represented by vertices, then and an edge A -> B could mean that process A is |
| 6 | +waiting for B to release its lock on a resource. |
| 7 | +""" |
| 8 | +from enum import Enum |
| 9 | + |
| 10 | + |
| 11 | +class TraversalState(Enum): |
| 12 | + WHITE = 0 |
| 13 | + GRAY = 1 |
| 14 | + BLACK = 2 |
| 15 | + |
| 16 | + |
| 17 | +example_graph_with_cycle = {'A': ['B', 'C'], |
| 18 | + 'B': ['D'], |
| 19 | + 'C': ['F'], |
| 20 | + 'D': ['E', 'F'], |
| 21 | + 'E': ['B'], |
| 22 | + 'F': []} |
| 23 | + |
| 24 | +example_graph_without_cycle = {'A': ['B', 'C'], |
| 25 | + 'B': ['D', 'E'], |
| 26 | + 'C': ['F'], |
| 27 | + 'D': ['E'], |
| 28 | + 'E': [], |
| 29 | + 'F': []} |
| 30 | + |
| 31 | + |
| 32 | +def is_in_cycle(graph, traversal_states, vertex): |
| 33 | + if traversal_states[vertex] == TraversalState.GRAY: |
| 34 | + return True |
| 35 | + traversal_states[vertex] = TraversalState.GRAY |
| 36 | + for neighbor in graph[vertex]: |
| 37 | + if is_in_cycle(graph, traversal_states, neighbor): |
| 38 | + return True |
| 39 | + traversal_states[vertex] = TraversalState.BLACK |
| 40 | + return False |
| 41 | + |
| 42 | + |
| 43 | +def contains_cycle(graph): |
| 44 | + traversal_states = {vertex: TraversalState.WHITE for vertex in graph} |
| 45 | + for vertex, state in traversal_states.items(): |
| 46 | + if (state == TraversalState.WHITE and |
| 47 | + is_in_cycle(graph, traversal_states, vertex)): |
| 48 | + return True |
| 49 | + return False |
| 50 | + |
| 51 | +print(contains_cycle(example_graph_with_cycle)) |
| 52 | +print(contains_cycle(example_graph_without_cycle)) |
0 commit comments