-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
docs, test: Fit Topological Sort algorithm to contributing guidelines #2835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
realstealthninja
merged 10 commits into
TheAlgorithms:master
from
HarshilShah1804:Harshil
Nov 1, 2024
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
4f10cbb
Modified docs,test of topological sort algorithm
HarshilShah1804 d9fc6e1
Update topological_sort.cpp
HarshilShah1804 68d067b
Merge branch 'master' into Harshil
HarshilShah1804 3816cb0
Merge branch 'TheAlgorithms:master' into Harshil
HarshilShah1804 5625480
Add class "Graph"
HarshilShah1804 457c03c
Update graph/topological_sort.cpp
HarshilShah1804 75bd9a3
Add namespace topological_sort
HarshilShah1804 de32a46
Merge branch 'master' into Harshil
HarshilShah1804 89d183d
Merge branch 'master' into Harshil
HarshilShah1804 b4ae7fa
Merge branch 'master' into Harshil
realstealthninja File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,189 @@ | ||
#include <algorithm> | ||
#include <iostream> | ||
#include <vector> | ||
|
||
int number_of_vertices, | ||
number_of_edges; // For number of Vertices (V) and number of edges (E) | ||
std::vector<std::vector<int>> graph; | ||
std::vector<bool> visited; | ||
std::vector<int> topological_order; | ||
|
||
void dfs(int v) { | ||
visited[v] = true; | ||
for (int u : graph[v]) { | ||
if (!visited[u]) { | ||
dfs(u); | ||
/** | ||
* @file | ||
* @brief [Topological Sort | ||
* Algorithm](https://en.wikipedia.org/wiki/Topological_sorting) | ||
* @details | ||
* Topological sorting of a directed graph is a linear ordering or its vertices | ||
* such that for every directed edge (u,v) from vertex u to vertex v, u comes | ||
* before v in the oredering. | ||
* | ||
* A topological sort is possible only in a directed acyclic graph (DAG). | ||
* This file contains code of finding topological sort using Kahn's Algorithm | ||
* which involves using Depth First Search technique | ||
*/ | ||
|
||
#include <algorithm> // For std::reverse | ||
#include <cassert> // For assert | ||
#include <iostream> // For IO operations | ||
#include <stack> // For std::stack | ||
#include <stdexcept> // For std::invalid_argument | ||
#include <vector> // For std::vector | ||
|
||
/** | ||
* @namespace graph | ||
* @brief Graph algorithms | ||
*/ | ||
namespace graph { | ||
|
||
/** | ||
* @namespace topological_sort | ||
* @brief Topological Sort Algorithm | ||
*/ | ||
namespace topological_sort { | ||
/** | ||
* @class Graph | ||
* @brief Class that represents a directed graph and provides methods for | ||
* manipulating the graph | ||
*/ | ||
class Graph { | ||
private: | ||
int n; // Number of nodes | ||
std::vector<std::vector<int>> adj; // Adjacency list representation | ||
|
||
public: | ||
/** | ||
* @brief Constructor for the Graph class | ||
* @param nodes Number of nodes in the graph | ||
*/ | ||
Graph(int nodes) : n(nodes), adj(nodes) {} | ||
|
||
/** | ||
* @brief Function that adds an edge between two nodes or vertices of graph | ||
* @param u Start node of the edge | ||
* @param v End node of the edge | ||
*/ | ||
void addEdge(int u, int v) { adj[u].push_back(v); } | ||
|
||
realstealthninja marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* @brief Get the adjacency list of the graph | ||
* @returns A reference to the adjacency list | ||
*/ | ||
const std::vector<std::vector<int>>& getAdjacencyList() const { | ||
return adj; | ||
} | ||
|
||
/** | ||
* @brief Get the number of nodes in the graph | ||
* @returns The number of nodes | ||
*/ | ||
int getNumNodes() const { return n; } | ||
}; | ||
|
||
/** | ||
* @brief Function to perform Depth First Search on the graph | ||
* @param v Starting vertex for depth-first search | ||
* @param visited Array representing whether each node has been visited | ||
* @param graph Adjacency list of the graph | ||
* @param s Stack containing the vertices for topological sorting | ||
*/ | ||
void dfs(int v, std::vector<int>& visited, | ||
const std::vector<std::vector<int>>& graph, std::stack<int>& s) { | ||
visited[v] = 1; | ||
for (int neighbour : graph[v]) { | ||
if (!visited[neighbour]) { | ||
dfs(neighbour, visited, graph, s); | ||
} | ||
} | ||
topological_order.push_back(v); | ||
s.push(v); | ||
} | ||
|
||
void topological_sort() { | ||
visited.assign(number_of_vertices, false); | ||
topological_order.clear(); | ||
for (int i = 0; i < number_of_vertices; ++i) { | ||
/** | ||
* @brief Function to get the topological sort of the graph | ||
* @param g Graph object | ||
* @returns A vector containing the topological order of nodes | ||
*/ | ||
std::vector<int> topologicalSort(const Graph& g) { | ||
int n = g.getNumNodes(); | ||
const auto& adj = g.getAdjacencyList(); | ||
std::vector<int> visited(n, 0); | ||
std::stack<int> s; | ||
|
||
for (int i = 0; i < n; i++) { | ||
if (!visited[i]) { | ||
dfs(i); | ||
dfs(i, visited, adj, s); | ||
} | ||
} | ||
reverse(topological_order.begin(), topological_order.end()); | ||
|
||
std::vector<int> ans; | ||
while (!s.empty()) { | ||
int elem = s.top(); | ||
s.pop(); | ||
ans.push_back(elem); | ||
} | ||
|
||
if (ans.size() < n) { // Cycle detected | ||
throw std::invalid_argument("cycle detected in graph"); | ||
} | ||
return ans; | ||
} | ||
int main() { | ||
std::cout | ||
<< "Enter the number of vertices and the number of directed edges\n"; | ||
std::cin >> number_of_vertices >> number_of_edges; | ||
int x = 0, y = 0; | ||
graph.resize(number_of_vertices, std::vector<int>()); | ||
for (int i = 0; i < number_of_edges; ++i) { | ||
std::cin >> x >> y; | ||
x--, y--; // to convert 1-indexed to 0-indexed | ||
graph[x].push_back(y); | ||
} | ||
topological_sort(); | ||
std::cout << "Topological Order : \n"; | ||
for (int v : topological_order) { | ||
std::cout << v + 1 | ||
<< ' '; // converting zero based indexing back to one based. | ||
} // namespace topological_sort | ||
} // namespace graph | ||
|
||
/** | ||
* @brief Self-test implementation | ||
* @returns void | ||
*/ | ||
static void test() { | ||
// Test 1 | ||
std::cout << "Testing for graph 1\n"; | ||
int n_1 = 6; | ||
graph::topological_sort::Graph graph1(n_1); | ||
graph1.addEdge(4, 0); | ||
graph1.addEdge(5, 0); | ||
graph1.addEdge(5, 2); | ||
graph1.addEdge(2, 3); | ||
graph1.addEdge(3, 1); | ||
graph1.addEdge(4, 1); | ||
std::vector<int> ans_1 = graph::topological_sort::topologicalSort(graph1); | ||
std::vector<int> expected_1 = {5, 4, 2, 3, 1, 0}; | ||
std::cout << "Topological Sorting Order: "; | ||
HarshilShah1804 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (int i : ans_1) { | ||
std::cout << i << " "; | ||
} | ||
std::cout << '\n'; | ||
assert(ans_1 == expected_1); | ||
std::cout << "Test Passed\n\n"; | ||
|
||
// Test 2 | ||
std::cout << "Testing for graph 2\n"; | ||
int n_2 = 5; | ||
graph::topological_sort::Graph graph2(n_2); | ||
graph2.addEdge(0, 1); | ||
graph2.addEdge(0, 2); | ||
graph2.addEdge(1, 2); | ||
graph2.addEdge(2, 3); | ||
graph2.addEdge(1, 3); | ||
graph2.addEdge(2, 4); | ||
std::vector<int> ans_2 = graph::topological_sort::topologicalSort(graph2); | ||
std::vector<int> expected_2 = {0, 1, 2, 4, 3}; | ||
std::cout << "Topological Sorting Order: "; | ||
for (int i : ans_2) { | ||
std::cout << i << " "; | ||
} | ||
std::cout << '\n'; | ||
assert(ans_2 == expected_2); | ||
std::cout << "Test Passed\n\n"; | ||
|
||
// Test 3 - Graph with cycle | ||
std::cout << "Testing for graph 3\n"; | ||
int n_3 = 3; | ||
graph::topological_sort::Graph graph3(n_3); | ||
graph3.addEdge(0, 1); | ||
graph3.addEdge(1, 2); | ||
graph3.addEdge(2, 0); | ||
try { | ||
graph::topological_sort::topologicalSort(graph3); | ||
} catch (std::invalid_argument& err) { | ||
assert(std::string(err.what()) == "cycle detected in graph"); | ||
} | ||
std::cout << "Test Passed\n"; | ||
} | ||
|
||
/** | ||
* @brief Main function | ||
* @returns 0 on exit | ||
*/ | ||
int main() { | ||
test(); // run self test implementations | ||
return 0; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.