Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 85d62bb

Browse files
HarshilShah1804realstealthninja
andauthored
docs, test: Fit Topological Sort algorithm to contributing guidelines (TheAlgorithms#2835)
* Modified docs,test of topological sort algorithm * Update topological_sort.cpp * Add class "Graph" * Update graph/topological_sort.cpp Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> * Add namespace topological_sort --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com>
1 parent 649a145 commit 85d62bb

File tree

1 file changed

+177
-38
lines changed

1 file changed

+177
-38
lines changed

‎graph/topological_sort.cpp

Lines changed: 177 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,189 @@
1-
#include <algorithm>
2-
#include <iostream>
3-
#include <vector>
4-
5-
int number_of_vertices,
6-
number_of_edges; // For number of Vertices (V) and number of edges (E)
7-
std::vector<std::vector<int>> graph;
8-
std::vector<bool> visited;
9-
std::vector<int> topological_order;
10-
11-
void dfs(int v) {
12-
visited[v] = true;
13-
for (int u : graph[v]) {
14-
if (!visited[u]) {
15-
dfs(u);
1+
/**
2+
* @file
3+
* @brief [Topological Sort
4+
* Algorithm](https://en.wikipedia.org/wiki/Topological_sorting)
5+
* @details
6+
* Topological sorting of a directed graph is a linear ordering or its vertices
7+
* such that for every directed edge (u,v) from vertex u to vertex v, u comes
8+
* before v in the oredering.
9+
*
10+
* A topological sort is possible only in a directed acyclic graph (DAG).
11+
* This file contains code of finding topological sort using Kahn's Algorithm
12+
* which involves using Depth First Search technique
13+
*/
14+
15+
#include <algorithm> // For std::reverse
16+
#include <cassert> // For assert
17+
#include <iostream> // For IO operations
18+
#include <stack> // For std::stack
19+
#include <stdexcept> // For std::invalid_argument
20+
#include <vector> // For std::vector
21+
22+
/**
23+
* @namespace graph
24+
* @brief Graph algorithms
25+
*/
26+
namespace graph {
27+
28+
/**
29+
* @namespace topological_sort
30+
* @brief Topological Sort Algorithm
31+
*/
32+
namespace topological_sort {
33+
/**
34+
* @class Graph
35+
* @brief Class that represents a directed graph and provides methods for
36+
* manipulating the graph
37+
*/
38+
class Graph {
39+
private:
40+
int n; // Number of nodes
41+
std::vector<std::vector<int>> adj; // Adjacency list representation
42+
43+
public:
44+
/**
45+
* @brief Constructor for the Graph class
46+
* @param nodes Number of nodes in the graph
47+
*/
48+
Graph(int nodes) : n(nodes), adj(nodes) {}
49+
50+
/**
51+
* @brief Function that adds an edge between two nodes or vertices of graph
52+
* @param u Start node of the edge
53+
* @param v End node of the edge
54+
*/
55+
void addEdge(int u, int v) { adj[u].push_back(v); }
56+
57+
/**
58+
* @brief Get the adjacency list of the graph
59+
* @returns A reference to the adjacency list
60+
*/
61+
const std::vector<std::vector<int>>& getAdjacencyList() const {
62+
return adj;
63+
}
64+
65+
/**
66+
* @brief Get the number of nodes in the graph
67+
* @returns The number of nodes
68+
*/
69+
int getNumNodes() const { return n; }
70+
};
71+
72+
/**
73+
* @brief Function to perform Depth First Search on the graph
74+
* @param v Starting vertex for depth-first search
75+
* @param visited Array representing whether each node has been visited
76+
* @param graph Adjacency list of the graph
77+
* @param s Stack containing the vertices for topological sorting
78+
*/
79+
void dfs(int v, std::vector<int>& visited,
80+
const std::vector<std::vector<int>>& graph, std::stack<int>& s) {
81+
visited[v] = 1;
82+
for (int neighbour : graph[v]) {
83+
if (!visited[neighbour]) {
84+
dfs(neighbour, visited, graph, s);
1685
}
1786
}
18-
topological_order.push_back(v);
87+
s.push(v);
1988
}
2089

21-
void topological_sort() {
22-
visited.assign(number_of_vertices, false);
23-
topological_order.clear();
24-
for (int i = 0; i < number_of_vertices; ++i) {
90+
/**
91+
* @brief Function to get the topological sort of the graph
92+
* @param g Graph object
93+
* @returns A vector containing the topological order of nodes
94+
*/
95+
std::vector<int> topologicalSort(const Graph& g) {
96+
int n = g.getNumNodes();
97+
const auto& adj = g.getAdjacencyList();
98+
std::vector<int> visited(n, 0);
99+
std::stack<int> s;
100+
101+
for (int i = 0; i < n; i++) {
25102
if (!visited[i]) {
26-
dfs(i);
103+
dfs(i, visited, adj, s);
27104
}
28105
}
29-
reverse(topological_order.begin(), topological_order.end());
106+
107+
std::vector<int> ans;
108+
while (!s.empty()) {
109+
int elem = s.top();
110+
s.pop();
111+
ans.push_back(elem);
112+
}
113+
114+
if (ans.size() < n) { // Cycle detected
115+
throw std::invalid_argument("cycle detected in graph");
116+
}
117+
return ans;
30118
}
31-
int main() {
32-
std::cout
33-
<< "Enter the number of vertices and the number of directed edges\n";
34-
std::cin >> number_of_vertices >> number_of_edges;
35-
int x = 0, y = 0;
36-
graph.resize(number_of_vertices, std::vector<int>());
37-
for (int i = 0; i < number_of_edges; ++i) {
38-
std::cin >> x >> y;
39-
x--, y--; // to convert 1-indexed to 0-indexed
40-
graph[x].push_back(y);
41-
}
42-
topological_sort();
43-
std::cout << "Topological Order : \n";
44-
for (int v : topological_order) {
45-
std::cout << v + 1
46-
<< ' '; // converting zero based indexing back to one based.
119+
} // namespace topological_sort
120+
} // namespace graph
121+
122+
/**
123+
* @brief Self-test implementation
124+
* @returns void
125+
*/
126+
static void test() {
127+
// Test 1
128+
std::cout << "Testing for graph 1\n";
129+
int n_1 = 6;
130+
graph::topological_sort::Graph graph1(n_1);
131+
graph1.addEdge(4, 0);
132+
graph1.addEdge(5, 0);
133+
graph1.addEdge(5, 2);
134+
graph1.addEdge(2, 3);
135+
graph1.addEdge(3, 1);
136+
graph1.addEdge(4, 1);
137+
std::vector<int> ans_1 = graph::topological_sort::topologicalSort(graph1);
138+
std::vector<int> expected_1 = {5, 4, 2, 3, 1, 0};
139+
std::cout << "Topological Sorting Order: ";
140+
for (int i : ans_1) {
141+
std::cout << i << " ";
142+
}
143+
std::cout << '\n';
144+
assert(ans_1 == expected_1);
145+
std::cout << "Test Passed\n\n";
146+
147+
// Test 2
148+
std::cout << "Testing for graph 2\n";
149+
int n_2 = 5;
150+
graph::topological_sort::Graph graph2(n_2);
151+
graph2.addEdge(0, 1);
152+
graph2.addEdge(0, 2);
153+
graph2.addEdge(1, 2);
154+
graph2.addEdge(2, 3);
155+
graph2.addEdge(1, 3);
156+
graph2.addEdge(2, 4);
157+
std::vector<int> ans_2 = graph::topological_sort::topologicalSort(graph2);
158+
std::vector<int> expected_2 = {0, 1, 2, 4, 3};
159+
std::cout << "Topological Sorting Order: ";
160+
for (int i : ans_2) {
161+
std::cout << i << " ";
47162
}
48163
std::cout << '\n';
164+
assert(ans_2 == expected_2);
165+
std::cout << "Test Passed\n\n";
166+
167+
// Test 3 - Graph with cycle
168+
std::cout << "Testing for graph 3\n";
169+
int n_3 = 3;
170+
graph::topological_sort::Graph graph3(n_3);
171+
graph3.addEdge(0, 1);
172+
graph3.addEdge(1, 2);
173+
graph3.addEdge(2, 0);
174+
try {
175+
graph::topological_sort::topologicalSort(graph3);
176+
} catch (std::invalid_argument& err) {
177+
assert(std::string(err.what()) == "cycle detected in graph");
178+
}
179+
std::cout << "Test Passed\n";
180+
}
181+
182+
/**
183+
* @brief Main function
184+
* @returns 0 on exit
185+
*/
186+
int main() {
187+
test(); // run self test implementations
49188
return 0;
50189
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /