2626namespace graph {
2727
2828/* *
29- * @brief Function that add edge between two nodes or vertices of graph
30- * @param u any node or vertex of graph
31- * @param v any node or vertex of graph
32- * @returns None
29+ * @class Graph
30+ * @brief Class that represents a directed graph and provides methods for
31+ * manipulating the graph
3332 */
34- void addEdge (std::vector<std::vector<int >>& adj, int u, int v) {
35- adj[u].push_back (v);
36- }
33+ class Graph {
34+ private:
35+ int n; // Number of nodes
36+ std::vector<std::vector<int >> adj; // Adjacency list representation
37+
38+ public:
39+ /* *
40+ * @brief Constructor for the Graph class
41+ * @param nodes Number of nodes in the graph
42+ */
43+ Graph (int nodes) : n(nodes), adj(nodes) {}
44+
45+ /* *
46+ * @brief Function that adds an edge between two nodes or vertices of graph
47+ * @param u Start node of the edge
48+ * @param v End node of the edge
49+ */
50+ void addEdge (int u, int v) { adj[u].push_back (v); }
51+
52+ /* *
53+ * @brief Get the adjacency list of the graph
54+ * @returns A reference to the adjacency list
55+ */
56+ const std::vector<std::vector<int >>& getAdjacencyList () const {
57+ return adj;
58+ }
59+
60+ /* *
61+ * @brief Get the number of nodes in the graph
62+ * @returns The number of nodes
63+ */
64+ int getNumNodes () const { return n; }
65+ };
3766
3867/* *
3968 * @brief Function to perform Depth First Search on the graph
40- * @param v starting vertex for depth first search
41- * @param vistied array representing if a node is visited
42- * @param graph adjecancy list of the graph
43- * @param s stack containing the vertex of topological sort
44- * @returns None
69+ * @param v Starting vertex for depth-first search
70+ * @param visited Array representing whether each node has been visited
71+ * @param graph Adjacency list of the graph
72+ * @param s Stack containing the vertices for topological sorting
4573 */
46- void dfs (int v, std::vector<int >& visited, std::vector<std::vector< int >>& graph,
47- std::stack<int >& s) {
74+ void dfs (int v, std::vector<int >& visited,
75+ const std::vector<std::vector< int >>& graph, std::stack<int >& s) {
4876 visited[v] = 1 ;
49- for (int i = 0 ; i < graph[v].size (); i++) {
50- int neighbour = graph[v][i];
77+ for (int neighbour : graph[v]) {
5178 if (!visited[neighbour]) {
5279 dfs (neighbour, visited, graph, s);
5380 }
@@ -57,25 +84,30 @@ void dfs(int v, std::vector<int>& visited, std::vector<std::vector<int>>& graph,
5784
5885/* *
5986 * @brief Function to get the topological sort of the graph
60- * @param graph adjecancy list of the graph
61- * @param n number of nodes in the graph
87+ * @param g Graph object
88+ * @returns A vector containing the topological order of nodes
6289 */
63- std::vector<int > topological_sort (std::vector<std::vector<int >>& graph, int n) {
90+ std::vector<int > topologicalSort (const Graph& g) {
91+ int n = g.getNumNodes ();
92+ const auto & adj = g.getAdjacencyList ();
6493 std::vector<int > visited (n, 0 );
6594 std::stack<int > s;
95+
6696 for (int i = 0 ; i < n; i++) {
6797 if (!visited[i]) {
68- dfs (i, visited, graph , s);
98+ dfs (i, visited, adj , s);
6999 }
70100 }
101+
71102 std::vector<int > ans;
72103 while (!s.empty ()) {
73104 int elem = s.top ();
74105 s.pop ();
75106 ans.push_back (elem);
76107 }
108+
77109 if (ans.size () < n) { // Cycle detected
78- throw std::invalid_argument (" cycle present in graph" );
110+ throw std::invalid_argument (" cycle detected in graph" );
79111 }
80112 return ans;
81113}
@@ -86,17 +118,17 @@ std::vector<int> topological_sort(std::vector<std::vector<int>>& graph, int n) {
86118 * @returns void
87119 */
88120static void test () {
89- // Test 1;
121+ // Test 1
90122 std::cout << " Testing for graph 1\n " ;
91123 int n_1 = 6 ;
92- std::vector<std::vector< int >> adj_1 (n_1);
93- graph:: addEdge (adj_1, 4 , 0 );
94- graph:: addEdge (adj_1, 5 , 0 );
95- graph:: addEdge (adj_1, 5 , 2 );
96- graph:: addEdge (adj_1, 2 , 3 );
97- graph:: addEdge (adj_1, 3 , 1 );
98- graph:: addEdge (adj_1, 4 , 1 );
99- std::vector<int > ans_1 = graph::topological_sort (adj_1, n_1 );
124+ graph::Graph graph1 (n_1);
125+ graph1. addEdge (4 , 0 );
126+ graph1. addEdge (5 , 0 );
127+ graph1. addEdge (5 , 2 );
128+ graph1. addEdge (2 , 3 );
129+ graph1. addEdge (3 , 1 );
130+ graph1. addEdge (4 , 1 );
131+ std::vector<int > ans_1 = graph::topologicalSort (graph1 );
100132 std::vector<int > expected_1 = {5 , 4 , 2 , 3 , 1 , 0 };
101133 std::cout << " Topological Sorting Order: " ;
102134 for (int i : ans_1) {
@@ -109,14 +141,14 @@ static void test() {
109141 // Test 2
110142 std::cout << " Testing for graph 2\n " ;
111143 int n_2 = 5 ;
112- std::vector<std::vector< int >> adj_2 (n_2);
113- graph:: addEdge (adj_2, 0 , 1 );
114- graph:: addEdge (adj_2, 0 , 2 );
115- graph:: addEdge (adj_2, 1 , 2 );
116- graph:: addEdge (adj_2, 2 , 3 );
117- graph:: addEdge (adj_2, 1 , 3 );
118- graph:: addEdge (adj_2, 2 , 4 );
119- std::vector<int > ans_2 = graph::topological_sort (adj_2, n_2 );
144+ graph::Graph graph2 (n_2);
145+ graph2. addEdge (0 , 1 );
146+ graph2. addEdge (0 , 2 );
147+ graph2. addEdge (1 , 2 );
148+ graph2. addEdge (2 , 3 );
149+ graph2. addEdge (1 , 3 );
150+ graph2. addEdge (2 , 4 );
151+ std::vector<int > ans_2 = graph::topologicalSort (graph2 );
120152 std::vector<int > expected_2 = {0 , 1 , 2 , 4 , 3 };
121153 std::cout << " Topological Sorting Order: " ;
122154 for (int i : ans_2) {
@@ -129,23 +161,23 @@ static void test() {
129161 // Test 3 - Graph with cycle
130162 std::cout << " Testing for graph 3\n " ;
131163 int n_3 = 3 ;
132- std::vector<std::vector< int >> adj_3 (n_3);
133- graph:: addEdge (adj_3, 0 , 1 );
134- graph:: addEdge (adj_3, 1 , 2 );
135- graph:: addEdge (adj_3, 2 , 0 );
164+ graph::Graph graph3 (n_3);
165+ graph3. addEdge (0 , 1 );
166+ graph3. addEdge (1 , 2 );
167+ graph3. addEdge (2 , 0 );
136168 try {
137- graph::topological_sort (adj_3, n_3 );
169+ graph::topologicalSort (graph3 );
138170 } catch (std::invalid_argument& err) {
139171 assert (std::string (err.what ()) == " cycle detected in graph" );
140172 }
141- std::cout << " Test Passed \n " ;
173+ std::cout << " Test Passed\n " ;
142174}
143175
144176/* *
145177 * @brief Main function
146178 * @returns 0 on exit
147179 */
148180int main () {
149- test (); // Self - test implementation
181+ test ();
150182 return 0 ;
151183}
0 commit comments