Skip to content

Commit 04cb5d0

Browse files
committed
topological sort shortest paths
1 parent 2525702 commit 04cb5d0

File tree

4 files changed

+165
-1
lines changed

4 files changed

+165
-1
lines changed

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,47 @@ g.addEdge(new jsgraphs.Edge(7, 2, 7.0));
425425

426426
var bf = new jsgraphs.BellmanFord(g, 0);
427427

428+
for(var v = 1; v < g.V; ++v){
429+
if(bf.hasPathTo(v)){
430+
var path = bf.pathTo(v);
431+
console.log('=====path from 0 to ' + v + ' start==========');
432+
for(var i = 0; i < path.length; ++i) {
433+
var e = path[i];
434+
console.log(e.from() + ' => ' + e.to() + ': ' + e.weight);
435+
}
436+
console.log('=====path from 0 to ' + v + ' end==========');
437+
console.log('=====distance: ' + bf.distanceTo(v) + '=========');
438+
}
439+
}
440+
```
441+
442+
### Find the shortest paths using Topological Sort Shortest Paths
443+
444+
The sample code below show how to obtain the shortest paths from a starting point 0 on a weighted directed acylic graph using Topological Sort:
445+
446+
```javascript
447+
var jsgraphs = require('js-graph-algorithms');
448+
var g = new jsgraphs.WeightedDiGraph(8);
449+
g.addEdge(new jsgraphs.Edge(0, 1, 5.0));
450+
g.addEdge(new jsgraphs.Edge(0, 4, 9.0));
451+
g.addEdge(new jsgraphs.Edge(0, 7, 8.0));
452+
g.addEdge(new jsgraphs.Edge(1, 2, 12.0));
453+
g.addEdge(new jsgraphs.Edge(1, 3, 15.0));
454+
g.addEdge(new jsgraphs.Edge(1, 7, 4.0));
455+
g.addEdge(new jsgraphs.Edge(2, 3, 3.0));
456+
g.addEdge(new jsgraphs.Edge(2, 6, 11.0));
457+
g.addEdge(new jsgraphs.Edge(3, 6, 9.0));
458+
g.addEdge(new jsgraphs.Edge(4, 5, 5.0));
459+
g.addEdge(new jsgraphs.Edge(4, 6, 20.0));
460+
g.addEdge(new jsgraphs.Edge(4, 7, 5.0));
461+
g.addEdge(new jsgraphs.Edge(5, 2, 1.0));
462+
g.addEdge(new jsgraphs.Edge(5, 6, 13.0));
463+
g.addEdge(new jsgraphs.Edge(7, 5, 6.0));
464+
g.addEdge(new jsgraphs.Edge(7, 2, 7.0));
465+
466+
467+
var bf = new jsgraphs.TopologicalSortShortestPaths(g, 0);
468+
428469
for(var v = 1; v < g.V; ++v){
429470
if(bf.hasPathTo(v)){
430471
var path = bf.pathTo(v);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "js-graph-algorithms",
3-
"version": "1.0.7",
3+
"version": "1.0.8",
44
"description": "Package implements data structures and algorithms for processing various types of graphs",
55
"author": "Xianshun Chen",
66
"contributors": [

src/jsgraphs.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,19 @@ var jsgraphs = jsgraphs || {};
448448
this.adjList[v].push(e);
449449
};
450450

451+
WeightedDiGraph.prototype.toDiGraph = function() {
452+
var g = new jss.DiGraph(this.V);
453+
for(var v = 0; v < this.V; ++v) {
454+
var adj_v = this.adjList[v];
455+
for (var i =0; i < adj_v.length; ++i) {
456+
var e = adj_v[i];
457+
var w = e.other(v);
458+
g.addEdge(v, w);
459+
}
460+
}
461+
return g;
462+
};
463+
451464
jss.WeightedDiGraph = WeightedDiGraph;
452465

453466
var DepthFirstSearch = function(G, s) {
@@ -904,6 +917,69 @@ var jsgraphs = jsgraphs || {};
904917
};
905918

906919
jss.BellmanFord = BellmanFord;
920+
921+
var TopologicalSortShortestPaths = function(G, s) {
922+
var V = G.V;
923+
this.s = s;
924+
this.marked = [];
925+
this.edgeTo = [];
926+
this.cost = [];
927+
928+
929+
for(var v =0; v < V; ++v){
930+
this.marked.push(false);
931+
this.edgeTo.push(null);
932+
this.cost.push(Number.MAX_VALUE);
933+
}
934+
935+
this.cost[s] = 0;
936+
this.marked[s] = true;
937+
938+
var order = new jss.TopologicalSort(G.toDiGraph()).order();
939+
940+
941+
for(var j = 0; j < order.length; ++j){
942+
var v = order[j];
943+
var adj_v = G.adj(v);
944+
for(var i = 0; i < adj_v.length; ++i) {
945+
var e = adj_v[i];
946+
this.relax(e);
947+
}
948+
}
949+
950+
951+
};
952+
953+
TopologicalSortShortestPaths.prototype.relax = function(e) {
954+
955+
var v = e.from();
956+
var w = e.to();
957+
958+
if(this.cost[w] > this.cost[v] + e.weight) {
959+
this.cost[w] = this.cost[v] + e.weight;
960+
this.marked[w] = true;
961+
this.edgeTo[w] = e;
962+
}
963+
};
964+
965+
TopologicalSortShortestPaths.prototype.hasPathTo = function(v) {
966+
return this.marked[v];
967+
};
968+
969+
970+
TopologicalSortShortestPaths.prototype.pathTo = function(v) {
971+
var path = new jss.Stack();
972+
for(var x = v; x != this.s; x = this.edgeTo[x].from()) {
973+
path.push(this.edgeTo[x]);
974+
}
975+
return path.toArray();
976+
};
977+
978+
TopologicalSortShortestPaths.prototype.distanceTo = function(v) {
979+
return this.cost[v];
980+
};
981+
982+
jss.TopologicalSortShortestPaths = TopologicalSortShortestPaths;
907983

908984
})(jsgraphs);
909985

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
var expect = require('chai').expect;
2+
var jsgraphs = require('../src/jsgraphs');
3+
4+
describe('Topological Sort Shortest Path', function(){
5+
it('should get shortest path from Weigthed Directed Acyclic Graph', function(){
6+
var g = new jsgraphs.WeightedDiGraph(8);
7+
g.addEdge(new jsgraphs.Edge(0, 1, 5.0));
8+
g.addEdge(new jsgraphs.Edge(0, 4, 9.0));
9+
g.addEdge(new jsgraphs.Edge(0, 7, 8.0));
10+
g.addEdge(new jsgraphs.Edge(1, 2, 12.0));
11+
g.addEdge(new jsgraphs.Edge(1, 3, 15.0));
12+
g.addEdge(new jsgraphs.Edge(1, 7, 4.0));
13+
g.addEdge(new jsgraphs.Edge(2, 3, 3.0));
14+
g.addEdge(new jsgraphs.Edge(2, 6, 11.0));
15+
g.addEdge(new jsgraphs.Edge(3, 6, 9.0));
16+
g.addEdge(new jsgraphs.Edge(4, 5, 5.0));
17+
g.addEdge(new jsgraphs.Edge(4, 6, 20.0));
18+
g.addEdge(new jsgraphs.Edge(4, 7, 5.0));
19+
g.addEdge(new jsgraphs.Edge(5, 2, 1.0));
20+
g.addEdge(new jsgraphs.Edge(5, 6, 13.0));
21+
g.addEdge(new jsgraphs.Edge(7, 5, 6.0));
22+
g.addEdge(new jsgraphs.Edge(7, 2, 7.0));
23+
24+
expect(g.V).to.equal(8);
25+
var edgeCount = 0;
26+
for(var v = 0; v < g.V; ++v){
27+
var adj_v = g.adj(v);
28+
edgeCount += adj_v.length;
29+
}
30+
expect(edgeCount).to.equal(16);
31+
32+
var ts = new jsgraphs.TopologicalSortShortestPaths(g, 0);
33+
34+
for(var v = 1; v < g.V; ++v){
35+
if(ts.hasPathTo(v)){
36+
var path = ts.pathTo(v);
37+
console.log('=====path from 0 to ' + v + ' start==========');
38+
for(var i = 0; i < path.length; ++i) {
39+
var e = path[i];
40+
console.log(e.from() + ' => ' + e.to() + ': ' + e.weight);
41+
}
42+
console.log('=====path from 0 to ' + v + ' end==========');
43+
console.log('=====distance: ' + ts.distanceTo(v) + '=========');
44+
}
45+
}
46+
});
47+
});

0 commit comments

Comments
 (0)