Open In App

Graph Cycle Detection in Java

Last Updated : 27 Apr, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

A graph is a complex data structure made up of nodes (also known as vertices) and edges that link pairs of nodes. Graphs are utilized to depict connections between various objects, with nodes typically symbolizing entities like cities, individuals, or websites, and edges denoting the connections or relationships between these entities.

Key Concepts of a graph

  • Node(Vertex): Each component within a graph is referred to as a vertex or node. Nodes can represent any entity, and they may hold additional information such as labels or attributes
  • Edge: An edge serves as a link between two nodes, signifying a connection or relationship between them. An edge may also hold information about the nature of the relationship.
  • Degree: The degree of a node in an undirected graph is the number of edges connected to it. Directed graphs have both in-degree (edges coming in) and out-degree (edges going out) for each node.

Graph

Cycle in a Graph

As the word suggests, a cycle forms a closed loop, which means starting and ending at the same vertex.

Graph Cycle in Directed Graph

Directed Graph: The edges in graphs have a direction associated with them they are called directed graphs

Follow the below steps to Implement the idea:

  • Create a recursive dfs function that has the following parameters – current vertex, visited array, and recursion stack.
  • Mark the current node as visited and also mark the index in the recursion stack.
  • Iterate a loop for all the vertices and for each vertex, call the recursive function if it is not yet visited (This step is done to make sure that if there is a forest of graphs, we are checking each forest):
  • In each recursion call, Find all the adjacent vertices of the current vertex which are not visited:
  • If an adjacent vertex is already marked in the recursion stack then return true.
  • Otherwise, call the recursive function for that adjacent vertex.
  • While returning from the recursion call, unmark the current node from the recursion stack, to represent that the current node is no longer a part of the path being traced.
  • If any of the functions returns true, stop the future function calls and return true as the answer.

Illustration Of Directed Graph

Directed_Graph

Program to Demonstrate the Graph Cycle Detection in Directed Graph

Below is the implementation for Graph cycle detection in directed graph:

Java
// A Java Program to detect cycle in a graph
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

class Graph {

    private final int V;
    private final List<List<Integer> > adj;

    public Graph(int V)
    {
        this.V = V;
        adj = new ArrayList<>(V);

        for (int i = 0; i < V; i++)
            adj.add(new LinkedList<>());
    }

    // Function to check if cycle exists
    private boolean isCyclicUtil(int i, boolean[] visited,
                                boolean[] recStack)
    {

        // Mark the current node as visited and
        // part of recursion stack
        if (recStack[i])
            return true;

        if (visited[i])
            return false;

        visited[i] = true;

        recStack[i] = true;
        List<Integer> children = adj.get(i);

        for (Integer c : children)
            if (isCyclicUtil(c, visited, recStack))
                return true;

        recStack[i] = false;

        return false;
    }

    private void addEdge(int source, int dest)
    {
        adj.get(source).add(dest);
    }

    // Returns true if the graph contains a
    // cycle, else false.
    private boolean isCyclic()
    {
        // Mark all the vertices as not visited and
        // not part of recursion stack
        boolean[] visited = new boolean[V];
        boolean[] recStack = new boolean[V];

        // Call the recursive helper function to
        // detect cycle in different DFS trees
        for (int i = 0; i < V; i++)
            if (isCyclicUtil(i, visited, recStack))
                return true;

        return false;
    }

    // Driver code
    public static void main(String[] args)
    {
        Graph graph = new Graph(4);
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(1, 2);
        graph.addEdge(2, 0);
        graph.addEdge(2, 3);
        graph.addEdge(3, 3);

        // Function call
        if (graph.isCyclic())
            System.out.println("Graph contains cycle");
        else
            System.out.println("Graph doesn't "
                            + "contain cycle");
    }
}

Output

Graph contains cycle

Complexity of the above Method:

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.

Cycle in Undirected Graph

Undirected Graph: The edges in graphs has no direction associated means that are two way for example, if there is a edge between u and v then there is also an edge between v and u.

Use DFS from every unvisited node. Depth First Traversal can be used to detect a cycle in a Graph. There is a cycle in a graph only if there is a back edge present in the graph. A back edge is an edge that is indirectly joining a node to itself (self-loop) or one of its ancestors in the tree produced by DFS.

To find the back edge to any of its ancestors keep a visited array and if there is a back edge to any visited node then there is a loop and return true.

Follow the below steps to implement the above approach:

  1. Iterate over all the nodes of the graph and Keep a visited array visited[] to track the visited nodes.
  2. Run a Depth First Traversal on the given subgraph connected to the current node and pass the parent of the current node.
    1. In each recursive
      • Set visited[root] a
    2. Iterate over all adjacent nodes of the current node in the adjacency list
      • If it is not visited then run DFS on that node and return true if it returns true.
      • Else if the adjacent node is visited and not the parent of the current node then return true.
  3. Return false.

Illustration Of Undirected Graph
Undirected_Graph

Program to Demonstrate the Graph Cycle Detection in UnDirected Graph

Below is the implementation for Graph cycle detection in undirected graph:

Java
// A Java Program to detect cycle in an undirected graph
import java.io.*;
import java.util.*;
@SuppressWarnings("unchecked")
// This class represents a
// directed graph using adjacency list
// representation
class Graph {
 
    // No. of vertices
    private int V;
 
    // Adjacency List Representation
    private LinkedList<Integer> adj[];
 
    // Constructor
    Graph(int v)
    {
        V = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; ++i)
            adj[i] = new LinkedList();
    }
 
    // Function to add an edge
    // into the graph
    void addEdge(int v, int w)
    {
        adj[v].add(w);
        adj[w].add(v);
    }
 
    // A recursive function that
    // uses visited[] and parent to detect
    // cycle in subgraph reachable
    // from vertex v.
    Boolean isCyclicUtil(int v, Boolean visited[],
                         int parent)
    {
        // Mark the current node as visited
        visited[v] = true;
        Integer i;
 
        // Recur for all the vertices
        // adjacent to this vertex
        Iterator<Integer> it = adj[v].iterator();
        while (it.hasNext()) {
            i = it.next();
 
            // If an adjacent is not
            // visited, then recur for that
            // adjacent
            if (!visited[i]) {
                if (isCyclicUtil(i, visited, v))
                    return true;
            }
 
            // If an adjacent is visited
            // and not parent of current
            // vertex, then there is a cycle.
            else if (i != parent)
                return true;
        }
        return false;
    }
 
    // Returns true if the graph
    // contains a cycle, else false.
    Boolean isCyclic()
    {
 
        // Mark all the vertices as
        // not visited and not part of
        // recursion stack
        Boolean visited[] = new Boolean[V];
        for (int i = 0; i < V; i++)
            visited[i] = false;
 
        // Call the recursive helper
        // function to detect cycle in
        // different DFS trees
        for (int u = 0; u < V; u++) {
 
            // Don't recur for u if already visited
            if (!visited[u])
                if (isCyclicUtil(u, visited, -1))
                    return true;
        }
 
        return false;
    }
 
    // Driver method to test above methods
    public static void main(String args[])
    {
 
        // Create a graph given
        // in the above diagram
        Graph g1 = new Graph(5);
        g1.addEdge(1, 0);
        g1.addEdge(0, 2);
        g1.addEdge(2, 1);
        g1.addEdge(0, 3);
        g1.addEdge(3, 4);
      
        if (g1.isCyclic())
            System.out.println("Graph contains cycle");
        else
            System.out.println("Graph doesn't contain cycle");
 
        Graph g2 = new Graph(3);
        g2.addEdge(0, 1);
        g2.addEdge(1, 2);
        if (g2.isCyclic())
            System.out.println("Graph contains cycle");
        else
            System.out.println("Graph doesn't contain cycle");
    }
}

Output

Graph contains cycle

Complexity of the above Method:

Time Complexity: O(V+E), The program does a simple DFS Traversal of the graph which is represented using an adjacency list. So the time complexity is O(V+E).
Auxiliary Space: O(V), To store the visited array O(V) space is required.


Next Article
Article Tags :
Practice Tags :

Similar Reads