Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python Program for Detect Cycle in a Directed Graph
A cycle occurs when a path starts and ends at the same vertex, following the direction of the edges. In directed graphs, cycles can cause problems like infinite loops or dependency errors, so detecting them is important in areas like task scheduling and deadlock detection.
We can use Depth-First Search (DFS) with a recursion stack to detect whether a cycle exists in a directed graph or not.
Problem Statement
You are given a directed graph represented using an adjacency list. Your task is to write a Python program to check whether the graph contains a cycle or not.
DFS-Based Cycle Detection
We use Depth-First Search (DFS) traversal and keep track of the nodes in the current recursion path. If we visit a node that is already in the recursion stack, it means a cycle exists.
Steps for DFS Cycle Detection
- Create a visited list to keep track of visited nodes.
- Use another list (recursion stack) to track the path of the current DFS.
- If a node is visited again while it is still in the recursion stack, a cycle is present.
- If all nodes are checked and no cycle is found, return False.
Graph Visualization
Python Implementation
Example 1: Graph with Cycle
Here's a complete implementation that detects cycles in a directed graph ?
def is_cyclic_util(v, visited, rec_stack, graph):
"""Helper function for cycle detection using DFS"""
visited[v] = True
rec_stack[v] = True
# Check all neighbors of current vertex
for neighbor in graph[v]:
if not visited[neighbor]:
if is_cyclic_util(neighbor, visited, rec_stack, graph):
return True
elif rec_stack[neighbor]:
return True # Back edge found - cycle detected
# Remove vertex from recursion stack before returning
rec_stack[v] = False
return False
def has_cycle(graph, num_vertices):
"""Main function to detect cycle in directed graph"""
visited = [False] * num_vertices
rec_stack = [False] * num_vertices
# Check each vertex as starting point
for vertex in range(num_vertices):
if not visited[vertex]:
if is_cyclic_util(vertex, visited, rec_stack, graph):
return True
return False
# Create graph with cycle: 0?1?2?3?1
num_vertices = 4
graph = [[] for _ in range(num_vertices)]
graph[0].append(1) # 0 ? 1
graph[1].append(2) # 1 ? 2
graph[2].append(3) # 2 ? 3
graph[3].append(1) # 3 ? 1 (creates cycle)
result = has_cycle(graph, num_vertices)
print(f"Graph contains cycle: {result}")
Graph contains cycle: True
Example 2: Graph without Cycle
Let's test with a directed acyclic graph (DAG) ?
def is_cyclic_util(v, visited, rec_stack, graph):
visited[v] = True
rec_stack[v] = True
for neighbor in graph[v]:
if not visited[neighbor]:
if is_cyclic_util(neighbor, visited, rec_stack, graph):
return True
elif rec_stack[neighbor]:
return True
rec_stack[v] = False
return False
def has_cycle(graph, num_vertices):
visited = [False] * num_vertices
rec_stack = [False] * num_vertices
for vertex in range(num_vertices):
if not visited[vertex]:
if is_cyclic_util(vertex, visited, rec_stack, graph):
return True
return False
# Create acyclic graph: 0?1?2?3
num_vertices = 4
acyclic_graph = [[] for _ in range(num_vertices)]
acyclic_graph[0].append(1) # 0 ? 1
acyclic_graph[1].append(2) # 1 ? 2
acyclic_graph[2].append(3) # 2 ? 3
result = has_cycle(acyclic_graph, num_vertices)
print(f"Acyclic graph contains cycle: {result}")
Acyclic graph contains cycle: False
How the Algorithm Works
The algorithm maintains two boolean arrays:
- visited[]: Tracks whether a vertex has been visited during DFS
- rec_stack[]: Tracks vertices in the current recursion path
A cycle exists when we encounter a vertex that is both visited and currently in the recursion stack, indicating a back edge.
Time and Space Complexity
| Aspect | Complexity | Explanation |
|---|---|---|
| Time | O(V + E) | Visit each vertex and edge once |
| Space | O(V) | Two boolean arrays of size V |
Conclusion
DFS with recursion stack efficiently detects cycles in directed graphs. The algorithm uses two boolean arrays to track visited nodes and current path, making it ideal for applications like deadlock detection and topological sorting validation.
