Skip to content

Commit 568ce00

Browse files
author
Felipe Ribeiro
committed
Merge branch 'tayllan-master'
2 parents 9767621 + 085c72e commit 568ce00

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed

algorithms/graph/bellman_ford.js

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* Copyright (C) 2014 Tayllan Búrigo
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to
6+
* deal in the Software without restriction, including without limitation the
7+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
* sell copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
* IN THE SOFTWARE.
21+
*/
22+
'use strict';
23+
24+
/**
25+
* Calculates the shortest paths in a graph to every node
26+
* from the node 'startNode' with Bellman-Ford's algorithm
27+
*
28+
* Worst Case Complexity: O(|V| * |E|), where |V| is the number of
29+
* vertices and |E| is the number of edges in the graph
30+
*
31+
* @param Object 'graph' An adjacency list representing the graph
32+
* @param String 'startNode' The starting node
33+
* @return Object the minimum distance to reach every vertice of
34+
* the graph starting in 'startNode', or an empty object if there
35+
* exists a Negative-Weighted Cycle in the graph
36+
*/
37+
var bellmanFord = function(graph, startNode) {
38+
var minDistance = {};
39+
var edges = [];
40+
var adjacencyListSize = 0;
41+
42+
// Add all the edges from the graph to the 'edges' array
43+
graph.vertices.forEach(function (s) {
44+
graph.neighbors(s).forEach(function(t) {
45+
edges.push({
46+
source: s,
47+
target: t,
48+
weight: graph.edge(s, t)
49+
});
50+
});
51+
52+
minDistance[s] = Infinity;
53+
++adjacencyListSize;
54+
});
55+
56+
minDistance[startNode] = 0;
57+
58+
var edgesSize = edges.length;
59+
var sourceDistance;
60+
var targetDistance;
61+
62+
for (var i = 0; i < adjacencyListSize - 1; i++) {
63+
for (var j = 0; j < edgesSize; j++) {
64+
sourceDistance = minDistance[edges[j].source] + edges[j].weight;
65+
targetDistance = minDistance[edges[j].target];
66+
67+
if (sourceDistance < targetDistance) {
68+
minDistance[edges[j].target] = sourceDistance;
69+
}
70+
}
71+
}
72+
73+
for (i = 0; i < edgesSize; i++) {
74+
sourceDistance = minDistance[edges[i].source] + edges[i].weight;
75+
targetDistance = minDistance[edges[i].target];
76+
77+
if (sourceDistance < targetDistance) {
78+
79+
// Empty 'distance' object indicates Negative-Weighted Cycle
80+
return {
81+
distance: {}
82+
};
83+
}
84+
}
85+
86+
return {
87+
distance: minDistance
88+
};
89+
};
90+
91+
module.exports = bellmanFord;

main.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ var lib = {
2525
Graph: {
2626
topologicalSort: require('./algorithms/graph/topological_sort'),
2727
dijkstra: require('./algorithms/graph/dijkstra'),
28-
SPFA: require('./algorithms/graph/SPFA')
28+
SPFA: require('./algorithms/graph/SPFA'),
29+
bellmanFord: require('./algorithms/graph/bellman_ford')
2930
},
3031
Math: {
3132
fibonacci: require('./algorithms/math/fibonacci'),

test/algorithms/graph/bellman_ford.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Copyright (C) 2014 Tayllan Búrigo
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"], to
6+
* deal in the Software without restriction, including without limitation the
7+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
* sell copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20+
* IN THE SOFTWARE.
21+
*/
22+
'use strict';
23+
24+
var bellmanFord = require('../../../algorithms/graph/bellman_ford'),
25+
Graph = require('../../../data_structures/graph'),
26+
assert = require('assert');
27+
28+
describe('Bellman-Ford Algorithm', function () {
29+
it('should return the shortest paths to all nodes from a given origin',
30+
function () {
31+
var graph = new Graph(true);
32+
33+
graph.addEdge('a', 'b', -1);
34+
graph.addEdge('a', 'c', 4);
35+
graph.addEdge('b', 'c', 3);
36+
graph.addEdge('b', 'd', 2);
37+
graph.addEdge('b', 'e', 2);
38+
graph.addEdge('d', 'b', 1);
39+
graph.addEdge('e', 'd', -3);
40+
graph.addEdge('d', 'c', 5);
41+
42+
var shortestPaths = bellmanFord(graph, 'a');
43+
44+
assert.equal(shortestPaths.distance.a, 0);
45+
assert.equal(shortestPaths.distance.d, -2);
46+
assert.equal(shortestPaths.distance.e, 1);
47+
48+
// It'll cause a Negative-Weighted Cycle.
49+
graph.addEdge('c', 'a', -9);
50+
51+
shortestPaths = bellmanFord(graph, 'a');
52+
53+
// The 'distance' object is empty
54+
assert.equal(shortestPaths.distance.a, undefined);
55+
});
56+
});

0 commit comments

Comments
 (0)