forked from trekhleb/javascript-algorithms
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
142 additions
and
5 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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 |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Bellman–Ford Algorithm | ||
|
||
The Bellman–Ford algorithm is an algorithm that computes shortest | ||
paths from a single source vertex to all of the other vertices | ||
in a weighted digraph. It is slower than Dijkstra's algorithm | ||
for the same problem, but more versatile, as it is capable of | ||
handling graphs in which some of the edge weights are negative | ||
numbers. | ||
|
||
 | ||
|
||
## Complexity | ||
|
||
Worst-case performance `O(|V||E|)` | ||
Best-case performance `O(|E|)` | ||
Worst-case space complexity `O(|V|)` | ||
|
||
## References | ||
|
||
- [Wikipedia](https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm) | ||
- [On YouTube by Michael Sambol](https://www.youtube.com/watch?v=obWXjtg0L64) |
56 changes: 56 additions & 0 deletions
56
src/algorithms/graph/bellman-ford/__test__/bellmanFord.test.js
This file contains 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 |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import GraphVertex from '../../../../data-structures/graph/GraphVertex'; | ||
import GraphEdge from '../../../../data-structures/graph/GraphEdge'; | ||
import Graph from '../../../../data-structures/graph/Graph'; | ||
import bellmanFord from '../bellmanFord'; | ||
|
||
describe('bellmanFord', () => { | ||
it('should find minimum paths to all vertices', () => { | ||
const vertexS = new GraphVertex('S'); | ||
const vertexE = new GraphVertex('E'); | ||
const vertexA = new GraphVertex('A'); | ||
const vertexD = new GraphVertex('D'); | ||
const vertexB = new GraphVertex('B'); | ||
const vertexC = new GraphVertex('C'); | ||
const vertexH = new GraphVertex('H'); | ||
|
||
const edgeSE = new GraphEdge(vertexS, vertexE, 8); | ||
const edgeSA = new GraphEdge(vertexS, vertexA, 10); | ||
const edgeED = new GraphEdge(vertexE, vertexD, 1); | ||
const edgeDA = new GraphEdge(vertexD, vertexA, -4); | ||
const edgeDC = new GraphEdge(vertexD, vertexC, -1); | ||
const edgeAC = new GraphEdge(vertexA, vertexC, 2); | ||
const edgeCB = new GraphEdge(vertexC, vertexB, -2); | ||
const edgeBA = new GraphEdge(vertexB, vertexA, 1); | ||
|
||
const graph = new Graph(true); | ||
graph | ||
.addVertex(vertexH) | ||
.addEdge(edgeSE) | ||
.addEdge(edgeSA) | ||
.addEdge(edgeED) | ||
.addEdge(edgeDA) | ||
.addEdge(edgeDC) | ||
.addEdge(edgeAC) | ||
.addEdge(edgeCB) | ||
.addEdge(edgeBA); | ||
|
||
const { distances, previousVertices } = bellmanFord(graph, vertexS); | ||
|
||
expect(distances).toEqual({ | ||
H: Infinity, | ||
S: 0, | ||
A: 5, | ||
B: 5, | ||
C: 7, | ||
D: 9, | ||
E: 8, | ||
}); | ||
|
||
expect(previousVertices.H).toBeNull(); | ||
expect(previousVertices.S).toBeNull(); | ||
expect(previousVertices.B.getKey()).toBe('C'); | ||
expect(previousVertices.C.getKey()).toBe('A'); | ||
expect(previousVertices.A.getKey()).toBe('D'); | ||
expect(previousVertices.D.getKey()).toBe('E'); | ||
}); | ||
}); |
This file contains 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 |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* @param {Graph} graph | ||
* @param {GraphVertex} startVertex | ||
* @return {{distances, previousVertices}} | ||
*/ | ||
export default function bellmanFord(graph, startVertex) { | ||
const distances = {}; | ||
const previousVertices = {}; | ||
|
||
// Init all distances with infinity assuming that currently we can't reach | ||
// any of the vertices except start one. | ||
distances[startVertex.getKey()] = 0; | ||
graph.getAllVertices().forEach((vertex) => { | ||
previousVertices[vertex.getKey()] = null; | ||
if (vertex.getKey() !== startVertex.getKey()) { | ||
distances[vertex.getKey()] = Infinity; | ||
} | ||
}); | ||
|
||
// We need (|V| - 1) iterations. | ||
for (let iteration = 0; iteration < (graph.getAllVertices().length - 1); iteration += 1) { | ||
// During each iteration go through all vertices. | ||
Object.keys(distances).forEach((vertexKey) => { | ||
const vertex = graph.getVertexByKey(vertexKey); | ||
|
||
// Go through all vertex edges. | ||
graph.getNeighbors(vertex).forEach((neighbor) => { | ||
const edge = graph.findEdge(vertex, neighbor); | ||
// Find out if the distance to the neighbor is shorter in this iteration | ||
// then in previous one. | ||
const distanceToVertex = distances[vertex.getKey()]; | ||
const distanceToNeighbor = distanceToVertex + edge.weight; | ||
if (distanceToNeighbor < distances[neighbor.getKey()]) { | ||
distances[neighbor.getKey()] = distanceToNeighbor; | ||
previousVertices[neighbor.getKey()] = vertex; | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
return { | ||
distances, | ||
previousVertices, | ||
}; | ||
} |
This file contains 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
This file contains 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
This file contains 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
This file contains 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