-
-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Added Floyd-Warshall algorithm implementation in the graph directory. #3081
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,210 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief [Floyd-Warshall Algorithm | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * (Floyd-Warshall All-Pairs Shortest Path)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * (https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @author [Mikes Tsampounaris](https://github.com/mikestsa) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @details | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Floyd-Warshall Algorithm is used to find the shortest paths between | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * all pairs of vertices in a weighted graph. The algorithm works with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * both positive and negative edge weights (but no negative cycles). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The algorithm uses dynamic programming approach. For each pair of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * vertices (i, j), it checks if going through an intermediate vertex k | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * provides a shorter path than the current known path. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Time Complexity: O(V^3) where V is the number of vertices. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Space Complexity: O(V^2) for the distance matrix. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <cassert> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <iostream> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <limits> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <vector> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constexpr int64_t INF = std::numeric_limits<int64_t>::max(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @namespace graph | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Graph Algorithms | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace graph { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Function that adds a directed edge between two vertices | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param adj adjacency matrix representation of the graph | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param u source vertex (1-indexed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param v destination vertex (1-indexed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param w weight of the edge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void addEdge(std::vector<std::vector<int64_t>>* adj, int u, int v, int64_t w) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (*adj)[u - 1][v - 1] = w; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+45
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Function runs the Floyd-Warshall algorithm and computes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * shortest paths between all pairs of vertices. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param adj adjacency matrix of the graph | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @return matrix containing shortest distances between all pairs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::vector<std::vector<int64_t>> floydWarshall( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::vector<std::vector<int64_t>>* adj) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// n denotes the number of vertices in graph | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| size_t n = adj->size(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// copy the adjacency matrix to dist | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::vector<std::vector<int64_t>> dist = *adj; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+56
to
+61
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::vector<std::vector<int64_t>>* adj) { | |
| /// n denotes the number of vertices in graph | |
| size_t n = adj->size(); | |
| /// copy the adjacency matrix to dist | |
| std::vector<std::vector<int64_t>> dist = *adj; | |
| const std::vector<std::vector<int64_t>>& adj) { | |
| /// n denotes the number of vertices in graph | |
| size_t n = adj.size(); | |
| /// copy the adjacency matrix to dist | |
| std::vector<std::vector<int64_t>> dist = adj; |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type mismatch between loop variable and container size. The variable 'i' is declared as 'int' but is being compared with 'n' which is 'size_t'. This can cause signed/unsigned comparison warnings. The loop variable should be 'size_t' to match the type of 'n'.
| for (int k = 0; k < n; k++) { | |
| /// for each source vertex i | |
| for (int i = 0; i < n; i++) { | |
| /// for each destination vertex j | |
| for (int j = 0; j < n; j++) { | |
| for (size_t k = 0; k < n; k++) { | |
| /// for each source vertex i | |
| for (size_t i = 0; i < n; i++) { | |
| /// for each destination vertex j | |
| for (size_t j = 0; j < n; j++) { |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type mismatch between loop variable and container size. The variable 'k' is declared as 'int' but is being compared with 'n' which is 'size_t'. This can cause signed/unsigned comparison warnings. The loop variable should be 'size_t' to match the type of 'n'.
| for (int k = 0; k < n; k++) { | |
| /// for each source vertex i | |
| for (int i = 0; i < n; i++) { | |
| /// for each destination vertex j | |
| for (int j = 0; j < n; j++) { | |
| for (size_t k = 0; k < n; k++) { | |
| /// for each source vertex i | |
| for (size_t i = 0; i < n; i++) { | |
| /// for each destination vertex j | |
| for (size_t j = 0; j < n; j++) { |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type mismatch between loop variable and container size. The variable 'j' is declared as 'int' but is being compared with 'n' which is 'size_t'. This can cause signed/unsigned comparison warnings. The loop variable should be 'size_t' to match the type of 'n'.
| for (int k = 0; k < n; k++) { | |
| /// for each source vertex i | |
| for (int i = 0; i < n; i++) { | |
| /// for each destination vertex j | |
| for (int j = 0; j < n; j++) { | |
| for (size_t k = 0; k < n; k++) { | |
| /// for each source vertex i | |
| for (size_t i = 0; i < n; i++) { | |
| /// for each destination vertex j | |
| for (size_t j = 0; j < n; j++) { |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential integer overflow when adding edge weights. The expression 'dist[i][k] + dist[k][j]' can overflow before the comparison with 'dist[i][j]' is performed, leading to incorrect shortest path calculations. Consider checking if the addition would overflow before performing it, or restructure the comparison to avoid addition.
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing bounds validation for vertex indices. The function should validate that 's' and 't' are within valid range (0 to n-1 where n is the matrix size) before accessing the matrix to prevent out-of-bounds access.
| if (dist[s][t] != INF) { | |
| return dist[s][t]; | |
| } | |
| // Validate indices to prevent out-of-bounds access | |
| if (s < 0 || t < 0) { | |
| return -1; | |
| } | |
| const size_t n = dist.size(); | |
| if (n == 0) { | |
| return -1; | |
| } | |
| const size_t rows = n; | |
| const size_t cols = dist[0].size(); | |
| const size_t si = static_cast<size_t>(s); | |
| const size_t ti = static_cast<size_t>(t); | |
| if (si >= rows || ti >= cols) { | |
| return -1; | |
| } | |
| if (dist[si][ti] != INF) { | |
| return dist[si][ti]; | |
| } |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicated matrix initialization pattern. The pattern of creating a matrix filled with INF and then setting diagonal elements to 0 appears in multiple test cases. Consider extracting this into a helper function to improve maintainability and reduce code duplication.
| /** Function to test the Algorithm */ | |
| void tests() { | |
| std::cout << "Initiating Predefined Tests..." << std::endl; | |
| std::cout << "Initiating Test 1..." << std::endl; | |
| std::vector<std::vector<int64_t>> adj1(4, std::vector<int64_t>(4, INF)); | |
| for (int i = 0; i < 4; i++) { | |
| adj1[i][i] = 0; | |
| } | |
| /** | |
| * @brief Helper function to create an n x n matrix initialized with INF | |
| * and 0 on the diagonal. | |
| * | |
| * @param n number of vertices (matrix dimension) | |
| * @return initialized adjacency matrix | |
| */ | |
| static std::vector<std::vector<int64_t>> createInitializedMatrix( | |
| std::size_t n) { | |
| std::vector<std::vector<int64_t>> matrix( | |
| n, std::vector<int64_t>(n, INF)); | |
| for (std::size_t i = 0; i < n; i++) { | |
| matrix[i][i] = 0; | |
| } | |
| return matrix; | |
| } | |
| /** Function to test the Algorithm */ | |
| void tests() { | |
| std::cout << "Initiating Predefined Tests..." << std::endl; | |
| std::cout << "Initiating Test 1..." << std::endl; | |
| std::vector<std::vector<int64_t>> adj1 = createInitializedMatrix(4); |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary explicit initialization with default constructor. The expression 'int()' is verbose and can simply be '0' or the variable can be left uninitialized since it's assigned before use. The same applies to the edges variable on this line.
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary explicit initialization with default constructor. The expressions 'int()' and 'int64_t()' are verbose. These variables can be declared without initialization since they are assigned values from user input before use.
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary explicit initialization with default constructor. The expressions 'int()' are verbose. These variables can be declared without initialization since they are assigned values from user input before use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function accepts a raw pointer to a vector, but a non-const reference would be more appropriate for this use case. Using a raw pointer suggests optional or ownership semantics, neither of which apply here. Consider changing the parameter to a non-const reference instead.