Java Program to Detect Cycle in a Directed Graph
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.
- Create an adjacency list with
- Input: Number of vertices,
- Add an Edge
- Input: Source vertex
src
and destination vertexdest
. - Output: Updated adjacency list with the edge added.
- Steps:
- Append the destination vertex
dest
to the adjacency list of the source vertexsrc
.
- Append the destination vertex
- Input: Source vertex
CycleDetection Class: Detecting Cycles
Algorithm to Detect Cycles using DFS
- Depth-First Search (DFS)
- Input: Current vertex
v
, arraysvisited
andrecStack
, graph objectgraph
. - Output:
True
if a cycle is detected, otherwiseFalse
. - Steps:
- If
recStack[v]
isTrue
, returnTrue
(cycle detected). - If
visited[v]
isTrue
, returnFalse
(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 vertexv
:- Recursively call
dfs(n, visited, recStack, graph)
. - If the recursive call returns
True
, returnTrue
(cycle detected).
- Recursively call
- Remove
v
from the recursion stack (recStack[v] = False
). - Return
False
(no cycle detected through this path).
- If
- Input: Current vertex
- Cycle Detection
- Input: Graph object
graph
. - Output:
True
if the graph contains a cycle, otherwiseFalse
. - Steps:
- Initialize arrays
visited
andrecStack
toFalse
for all vertices. - For each vertex
v
in the graph:- If
visited[v]
isFalse
, calldfs(v, visited, recStack, graph)
. - If
dfs
returnsTrue
, returnTrue
(cycle detected).
- If
- Return
False
(no cycle detected)
- Initialize arrays
- Input: Graph object
Implementation cycle detection using DFS in 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.");
}
}
}
Output
The 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.
- Create an adjacency list with
Add an Edge
- Input: Source vertex
v
and destination vertexw
. - Output: Updated adjacency list with the edge added.
- Procedure:
- Append the destination vertex
w
to the adjacency list of the source vertexv
.
- Append the destination vertex
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
whereinDegree[i]
is the in-degree of vertexi
. - Procedure:
- Initialize an array
inDegree
of sizeV
to store the in-degrees of all vertices. - Iterate over each vertex
u
in the graph. - For each adjacent vertex
v
ofu
, incrementinDegree[v]
by 1.
- Initialize an array
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, enqueueu
intoq
.
- Initialize an empty queue
Perform BFS and Check for Cycles
- Input: The queue
q
, adjacency listadj
, and arrayinDegree
. - 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
fromq
. - Increment the
visited
counter. - For each adjacent vertex
v
ofu
:- Decrement
inDegree[v]
by 1. - If
inDegree[v]
becomes 0, enqueuev
intoq
.
- Decrement
- Dequeue a vertex
- If the
visited
counter is not equal to the number of verticesV
, returntrue
(the graph contains a cycle). - Otherwise, return
false
.
- Initialize a counter
Implementation cycle detection using Topological Sorting in 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.");
}
}
}
Output
Graph 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.