Skip to content

Commit 7988713

Browse files
authored
feat: floyd-warshall for all pairs shortest path (TheAlgorithms#143)
* feat: floyd-warshall for all pairs shortest path * rewrite incorrect comments
1 parent 042f52c commit 7988713

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

graph/floyd_warshall.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @function floydWarshall
3+
* @description Compute the shortest path for all pairs of nodes for a graph without negative weight edges. The input graph is a adjacency matrix, where graph[i][j] holds the weight of edges a->b. If the edge does not exist, the value in the matrix is Infinity.
4+
* @Complexity_Analysis
5+
* Time complexity: O(V^3)
6+
* Space Complexity: O(V^2). This space is required to hold the result
7+
* @param {number[][]} graph - The graph in adjacency matrix form
8+
* @return {number[][]} - A matrix holding the shortest path for each pair of nodes. matrix[i][j] holds the distance of the shortest path (i -> j).
9+
* @see https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
10+
*/
11+
export const floydWarshall = (graph: number[][]): number[][] => {
12+
let distances = structuredClone(graph);
13+
let N = graph.length;
14+
15+
// We begin by setting the weighted adjacency matrix as the shortest paths.
16+
// For the k'th iteration, we try to relax the shortest paths by including node k in the path.
17+
for (let k = 0; k < N; ++k) {
18+
let newDistances = [];
19+
for (let i = 0; i < N; ++i) {
20+
newDistances.push(Array(N).fill(Infinity));
21+
}
22+
23+
for (let i = 0; i < N; ++i) {
24+
for (let j = 0; j < N; ++j) {
25+
// The shortest path from node i to j is the minimum of:
26+
// 1. the shortest path (i -> j) without node k
27+
// 2. the sum of the shortest path (i -> k) and (k -> j)
28+
newDistances[i][j] = Math.min(distances[i][j], distances[i][k] + distances[k][j]);
29+
}
30+
}
31+
distances = newDistances;
32+
}
33+
34+
return distances;
35+
}
36+
37+

graph/test/floyd_warshall.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { floydWarshall } from "../floyd_warshall";
2+
3+
describe("floydWarshall", () => {
4+
it("should return the correct value for zero element graph", () => {
5+
expect(floydWarshall([])).toEqual([]);
6+
});
7+
8+
it("should return the correct value for one element graph", () => {
9+
expect(floydWarshall([[1]])).toStrictEqual([[1]]);
10+
});
11+
12+
it("should return the correct value for two element graph", () => {
13+
expect(floydWarshall([[10, 4], [3, 6]])).toStrictEqual([[7, 4], [3, 6]]);
14+
});
15+
16+
it("should return the correct value", () => {
17+
let graph = [];
18+
for (let i = 1; i <= 5; ++i) {
19+
let arr = [];
20+
for (let j = 1; j <= 5; ++j) {
21+
arr.push(i * j);
22+
}
23+
graph.push(arr);
24+
}
25+
26+
let expected = [
27+
[ 1, 2, 3, 4, 5 ],
28+
[ 2, 4, 5, 6, 7 ],
29+
[ 3, 5, 6, 7, 8 ],
30+
[ 4, 6, 7, 8, 9 ],
31+
[ 5, 7, 8, 9, 10 ]
32+
];
33+
expect(floydWarshall(graph)).toStrictEqual(expected);
34+
});
35+
36+
it("should return the correct value", () => {
37+
let graph = [
38+
[0, 4, Infinity, Infinity, Infinity, Infinity, Infinity, 8, Infinity],
39+
[4, 0, 8, Infinity, Infinity, Infinity, Infinity, 11, Infinity],
40+
[Infinity, 8, 0, 7, Infinity, 4, Infinity, Infinity, 2],
41+
[Infinity, Infinity, 7, 0, 9, 14, Infinity, Infinity, Infinity],
42+
[Infinity, Infinity, Infinity, 9, 0, 10, Infinity, Infinity, Infinity],
43+
[Infinity, Infinity, 4, 14, 10, 0, 2, Infinity, Infinity],
44+
[Infinity, Infinity, Infinity, Infinity, Infinity, 2, 0, 1, 6],
45+
[8, 11, Infinity, Infinity, Infinity, Infinity, 1, 0, 7],
46+
[Infinity, Infinity, 2, Infinity, Infinity, Infinity, 6, 7, 0]
47+
];
48+
49+
let expected = [
50+
[0, 4, 12, 19, 21, 11, 9, 8, 14],
51+
[4, 0, 8, 15, 22, 12, 12, 11, 10],
52+
[12, 8, 0, 7, 14, 4, 6, 7, 2],
53+
[19, 15, 7, 0, 9, 11, 13, 14, 9],
54+
[21, 22, 14, 9, 0, 10, 12, 13, 16],
55+
[11, 12, 4, 11, 10, 0, 2, 3, 6],
56+
[9, 12, 6, 13, 12, 2, 0, 1, 6],
57+
[8, 11, 7, 14, 13, 3, 1, 0, 7],
58+
[14, 10, 2, 9, 16, 6, 6, 7, 0]
59+
]
60+
61+
expect(floydWarshall(graph)).toStrictEqual(expected);
62+
});
63+
});

0 commit comments

Comments
 (0)