Java Program to Detect Cycle in a Directed Graph
Last Updated :
29 Jul, 2024
Given a directed graph, check whether the graph contains a cycle. Your function should return true if the given graph contains at least one cycle; otherwise, it should return false.
Example:
Input: N = 4, E = 6
Output: Yes
Explanation: The diagram clearly shows a cycle 0 -> 2 -> 0
Input: N = 4, E = 4
Output: No
Explanation: The diagram clearly shows no cycle.
Approaches For Cycle Detection
There are two approaches to detect cycles in a directed graph:
- Depth-First Search (DFS)
- Kahn's Algorithm (Topological Sorting)
1. Java Program to Detect Cycle in a Directed Graph using (DFS)
The DFS approach is a popular method for cycle detection in directed graphs. The key idea is to use a recursive function to traverse the graph and maintain two arrays: one for visited nodes and another for nodes currently in the recursion stack (or "visiting" set). If we encounter a node that is already in the recursion stack, a cycle is detected.
- visited[]: To track whether a node has been visited.
- recStack[]: To keep track of nodes currently in the recursion stack.
Graph Class: Representing the Directed Graph
Algorithm to Create a Graph
- Initialize the Graph
- Input: Number of vertices,
V
. - Output: An empty graph with
V
vertices. - Steps:
- Create an adjacency list with
V
empty lists. - Initialize each list to represent the neighbors of each vertex.
- Add an Edge
- Input: Source vertex
src
and destination vertex dest
. - Output: Updated adjacency list with the edge added.
- Steps:
- Append the destination vertex
dest
to the adjacency list of the source vertex src
.
CycleDetection Class: Detecting Cycles
Algorithm to Detect Cycles using DFS
- Depth-First Search (DFS)
- Input: Current vertex
v
, arrays visited
and recStack
, graph object graph
. - Output:
True
if a cycle is detected, otherwise False
. - Steps:
- If
recStack[v]
is True
, return True
(cycle detected). - If
visited[v]
is True
, return False
(no cycle through this vertex). - Mark
v
as visited (visited[v] = True
). - Add
v
to the recursion stack (recStack[v] = True
). - For each neighbor
n
of vertex v
:- Recursively call
dfs(n, visited, recStack, graph)
. - If the recursive call returns
True
, return True
(cycle detected).
- Remove
v
from the recursion stack (recStack[v] = False
). - Return
False
(no cycle detected through this path).
- Cycle Detection
- Input: Graph object
graph
. - Output:
True
if the graph contains a cycle, otherwise False
. - Steps:
- Initialize arrays
visited
and recStack
to False
for all vertices. - For each vertex
v
in the graph:- If
visited[v]
is False
, call dfs(v, visited, recStack, graph)
. - If
dfs
returns True
, return True
(cycle detected).
- Return
False
(no cycle detected)
Implementation cycle detection using DFS in Java:
Java
import java.util.ArrayList;
import java.util.List;
// Graph class representing a directed
// graph using adjacency list
class Graph {
private final int vertices;
private final List<List<Integer>> adjList;
public Graph(int vertices) {
this.vertices = vertices;
adjList = new ArrayList<>(vertices);
for (int i = 0; i < vertices; i++) {
adjList.add(new ArrayList<>());
}
}
public void addEdge(int src, int dest) {
adjList.get(src).add(dest);
}
public List<Integer> getNeighbors(int vertex) {
return adjList.get(vertex);
}
public int getVertices() {
return vertices;
}
}
// CycleDetection class to detect cycles in the graph
class CycleDetection {
private boolean dfs(int vertex, boolean[] visited, boolean[] recStack, Graph graph) {
if (recStack[vertex]) {
return true;
}
if (visited[vertex]) {
return false;
}
visited[vertex] = true;
recStack[vertex] = true;
for (int neighbor : graph.getNeighbors(vertex)) {
if (dfs(neighbor, visited, recStack, graph)) {
return true;
}
}
recStack[vertex] = false;
return false;
}
public boolean hasCycle(Graph graph) {
int vertices = graph.getVertices();
boolean[] visited = new boolean[vertices];
boolean[] recStack = new boolean[vertices];
for (int i = 0; i < vertices; i++) {
if (!visited[i] && dfs(i, visited, recStack, graph)) {
return true;
}
}
return false;
}
}
// Main class to demonstrate the cycle detection
public class Main {
public static void main(String[] args) {
Graph graph = new Graph(4);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
graph.addEdge(2, 3);
CycleDetection cycleDetection = new CycleDetection();
boolean hasCycle = cycleDetection.hasCycle(graph);
if (hasCycle) {
System.out.println("The graph contains a cycle.");
} else {
System.out.println("The graph does not contain a cycle.");
}
}
}
OutputThe graph contains a cycle.
- Time Complexity: O(V + E), the Time Complexity of this method is the same as the time complexity of DFS traversal which is O(V+E).
- Auxiliary Space: O(V). To store the visited and recursion stack O(V) space is needed.
2. Java Program to Detect Cycle in a Directed Graph using Topological Sorting:
Kahn's algorithm can also be used to detect cycles. It involves calculating the in-degree (number of incoming edges) for each vertex. If at any point the number of processed vertices is less than the total number of vertices, a cycle exists.
Initialize the Graph
- Input: Number of vertices
V
. - Output: An initialized graph with an adjacency list.
- Procedure:
- Create an adjacency list with
V
empty lists. - Initialize each list to represent the neighbors of each vertex.
Add an Edge
- Input: Source vertex
v
and destination vertex w
. - Output: Updated adjacency list with the edge added.
- Procedure:
- Append the destination vertex
w
to the adjacency list of the source vertex v
.
Cycle Detection: Using Kahn's Algorithm (Topological Sorting)
Calculate In-Degree of Each Vertex
- Input: The graph represented as an adjacency list.
- Output: An array
inDegree
where inDegree[i]
is the in-degree of vertex i
. - Procedure:
- Initialize an array
inDegree
of size V
to store the in-degrees of all vertices. - Iterate over each vertex
u
in the graph. - For each adjacent vertex
v
of u
, increment inDegree[v]
by 1.
Enqueue Vertices with 0 In-Degree
- Input: The array
inDegree
. - Output: A queue
q
containing vertices with 0 in-degree. - Procedure:
- Initialize an empty queue
q
. - Iterate over each vertex
u
. - If
inDegree[u]
is 0, enqueue u
into q
.
Perform BFS and Check for Cycles
- Input: The queue
q
, adjacency list adj
, and array inDegree
. - Output: A boolean value indicating if the graph contains a cycle.
- Procedure:
- Initialize a counter
visited
to count the number of visited vertices. - While the queue
q
is not empty:- Dequeue a vertex
u
from q
. - Increment the
visited
counter. - For each adjacent vertex
v
of u
:- Decrement
inDegree[v]
by 1. - If
inDegree[v]
becomes 0, enqueue v
into q
.
- If the
visited
counter is not equal to the number of vertices V
, return true
(the graph contains a cycle). - Otherwise, return
false
.
Implementation cycle detection using Topological Sorting in Java:
Java
// Java Program to detect cycle in a graph
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
class Graph {
private int V; // number of vertices
private ArrayList<ArrayList<Integer> >
adj; // adjacency list
public Graph(int V)
{
this.V = V;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
}
public void addEdge(int v, int w) { adj.get(v).add(w); }
public boolean isCyclic()
{
int[] inDegree
= new int[V]; // stores in-degree of each vertex
Queue<Integer> q
= new LinkedList<>(); // queue to store vertices
// with 0 in-degree
int visited = 0; // count of visited vertices
// calculate in-degree of each vertex
for (int u = 0; u < V; u++) {
for (int v : adj.get(u)) {
inDegree[v]++;
}
}
// enqueue vertices with 0 in-degree
for (int u = 0; u < V; u++) {
if (inDegree[u] == 0) {
q.add(u);
}
}
// BFS traversal
while (!q.isEmpty()) {
int u = q.poll();
visited++;
// reduce in-degree of adjacent vertices
for (int v : adj.get(u)) {
inDegree[v]--;
// if in-degree becomes 0, enqueue the
// vertex
if (inDegree[v] == 0) {
q.add(v);
}
}
}
return visited != V; // if not all vertices are
// visited, there is a cycle
}
}
// Driver code
public class Main {
public static void main(String[] args)
{
Graph g = new Graph(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(4, 1);
g.addEdge(4, 5);
g.addEdge(5, 3);
if (g.isCyclic()) {
System.out.println("Graph contains cycle.");
}
else {
System.out.println(
"Graph does not contain cycle.");
}
}
}
OutputGraph does not contain cycle.
Time Complexity: O(V + E), the time complexity of this method is the same as the time complexity of DFS traversal which is O(V+E).
Auxiliary Space: O(V). To store the visited and recursion stack O(V) space is needed.