diff --git a/graph/cycle_check_directed_graph.cpp b/graph/cycle_check_directed_graph.cpp index 0f7b84cd3..a9e4f2c8b 100644 --- a/graph/cycle_check_directed_graph.cpp +++ b/graph/cycle_check_directed_graph.cpp @@ -1,21 +1,19 @@ /** - * Copyright 2020 * @file cycle_check_directed graph.cpp * * @brief BFS and DFS algorithms to check for cycle in a directed graph. * - * @author Anmol3299 - * contact: mittalanmol22@gmail.com + * @author [Anmol3299](mailto:mittalanmol22@gmail.com) * */ -#include // for std::cout -#include // for std::queue -#include // for throwing errors -#include // for std::remove_reference_t -#include // for std::unordered_map -#include // for std::move -#include // for std::vector +#include // for std::cout +#include // for std::map +#include // for std::queue +#include // for throwing errors +#include // for std::remove_reference +#include // for std::move +#include // for std::vector /** * Implementation of non-weighted directed edge of a graph. @@ -43,7 +41,7 @@ struct Edge { : src(source), dest(destination) {} }; -using AdjList = std::unordered_map>; +using AdjList = std::map>; /** * Implementation of graph class. @@ -76,7 +74,7 @@ class Graph { * @param adjList is the adjacency list representation of graph. */ Graph(unsigned int vertices, AdjList&& adjList) - : m_vertices(std::move(vertices)), m_adjList(std::move(adjList)) {} + : m_vertices(vertices), m_adjList(std::move(adjList)) {} /** Create a graph from vertices and a set of edges. * @@ -102,16 +100,14 @@ class Graph { * * @return const reference to the adjacency list */ - std::remove_reference_t const& getAdjList() const { + std::remove_reference::type const& getAdjList() const { return m_adjList; } /** * @return number of vertices in the graph. */ - std::remove_reference_t const& getVertices() const { - return m_vertices; - } + unsigned int getVertices() const { return m_vertices; } /** Add vertices in the graph. * @@ -150,6 +146,15 @@ class Graph { AdjList m_adjList; }; +/** + * Check if a directed graph has a cycle or not. + * + * This class provides 2 methods to check for cycle in a directed graph: + * isCyclicDFS & isCyclicBFS. + * + * - isCyclicDFS uses DFS traversal method to check for cycle in a graph. + * - isCyclidBFS used BFS traversal method to check for cycle in a graph. + */ class CycleCheck { private: enum nodeStates : uint8_t { not_visited = 0, in_stack, visited }; @@ -170,12 +175,13 @@ class CycleCheck { // If the node has children, then recursively visit all children of the // node. - if (auto const& it = adjList.find(node); it != adjList.end()) { + auto const it = adjList.find(node); + if (it != adjList.end()) { for (auto child : it->second) { // If state of child node is "not_visited", evaluate that child // for presence of cycle. - if (auto state_of_child = (*state)[child]; - state_of_child == not_visited) { + auto state_of_child = (*state)[child]; + if (state_of_child == not_visited) { if (isCyclicDFSHelper(adjList, state, child)) { return true; } @@ -204,6 +210,8 @@ class CycleCheck { * @return true if a cycle is detected, else false. */ static bool isCyclicDFS(Graph const& graph) { + auto vertices = graph.getVertices(); + /** State of the node. * * It is a vector of "nodeStates" which represents the state node is in. @@ -211,10 +219,10 @@ class CycleCheck { * * Initially, all nodes are in "not_visited" state. */ - std::vector state(graph.getVertices(), not_visited); + std::vector state(vertices, not_visited); // Start visiting each node. - for (auto node = 0; node < graph.getVertices(); node++) { + for (unsigned int node = 0; node < vertices; node++) { // If a node is not visited, only then check for presence of cycle. // There is no need to check for presence of cycle for a visited // node as it has already been checked for presence of cycle. @@ -239,18 +247,20 @@ class CycleCheck { * @return true if a cycle is detected, else false. */ static bool isCyclicBFS(Graph const& graph) { - AdjList graphAjdList = graph.getAdjList(); + auto graphAjdList = graph.getAdjList(); + auto vertices = graph.getVertices(); - std::vector indegree(graph.getVertices(), 0); + std::vector indegree(vertices, 0); // Calculate the indegree i.e. the number of incident edges to the node. - for (auto const& [parent, children] : graphAjdList) { + for (auto const& list : graphAjdList) { + auto children = list.second; for (auto const& child : children) { indegree[child]++; } } std::queue can_be_solved; - for (auto node = 0; node < graph.getVertices(); node++) { + for (unsigned int node = 0; node < vertices; node++) { // If a node doesn't have any input edges, then that node will // definately not result in a cycle and can be visited safely. if (!indegree[node]) { @@ -259,17 +269,18 @@ class CycleCheck { } // Vertices that need to be traversed. - auto remain = graph.getVertices(); + auto remain = vertices; // While there are safe nodes that we can visit. while (!can_be_solved.empty()) { - auto front = can_be_solved.front(); + auto solved = can_be_solved.front(); // Visit the node. can_be_solved.pop(); // Decrease number of nodes that need to be traversed. remain--; // Visit all the children of the visited node. - if (auto it = graphAjdList.find(front); it != graphAjdList.end()) { + auto it = graphAjdList.find(solved); + if (it != graphAjdList.end()) { for (auto child : it->second) { // Check if we can visited the node safely. if (--indegree[child] == 0) {