├── index.js ├── .gitignore ├── third-party-libs └── vis │ ├── img │ └── network │ │ ├── cross.png │ │ ├── minus.png │ │ ├── plus.png │ │ ├── cross2.png │ │ ├── upArrow.png │ │ ├── backIcon.png │ │ ├── deleteIcon.png │ │ ├── downArrow.png │ │ ├── editIcon.png │ │ ├── leftArrow.png │ │ ├── rightArrow.png │ │ ├── addNodeIcon.png │ │ ├── connectIcon.png │ │ ├── zoomExtends.png │ │ └── acceptDeleteIcon.png │ ├── vis-network.min.css │ ├── vis-timeline-graph2d.min.css │ └── vis.min.css ├── .travis.yml ├── test ├── quick-union-spec.js ├── topological-sort-spec.js ├── min-pq-spec.js ├── graph-spec.js ├── queue-spec.js ├── connected-components-spec.js ├── depth-first-search-spec.js ├── breadth-first-search-spec.js ├── index-min-pq-spec.js ├── directed-graph-spec.js ├── stack-spec.js ├── strongly-connected-components-spec.js ├── flow-network-spec.js ├── weighted-digraph-spec.js ├── kruskal-spec.js ├── lazy-prim-spec.js ├── eager-prim-mst-spec.js ├── ford-fulkerson-spec.js ├── bellman-ford-spec.js ├── dijkstra-spec.js ├── weighted-graph-spec.js └── topoloical-sort-shortest-paths-spec.js ├── Gruntfile.js ├── LICENSE ├── package.json ├── examples ├── example-graph.html ├── example-dfs.html ├── example-digraph.html ├── example-connected-components.html ├── example-weighted-digraph.html ├── example-strongly-connected-components.html ├── example-weighted-graph.html ├── example-topo-sort.html ├── example-kruskal.html ├── example-lazy-prim.html ├── example-eager-prim.html ├── example-ford-fulkerson.html └── example-dijkstra.html ├── src ├── jsgraphs.d.ts └── jsgraphs.js └── README.md /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src/jsgraphs'); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | thumbs.db 4 | *.log 5 | node_modules/ 6 | .idea -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/cross.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/minus.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/plus.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/cross2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/cross2.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/upArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/upArrow.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/backIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/backIcon.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/deleteIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/deleteIcon.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/downArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/downArrow.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/editIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/editIcon.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/leftArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/leftArrow.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/rightArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/rightArrow.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "stable" 4 | 5 | before_script: 6 | - npm install -g grunt-cli 7 | 8 | after_success: 9 | - npm run coveralls -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/addNodeIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/addNodeIcon.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/connectIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/connectIcon.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/zoomExtends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/zoomExtends.png -------------------------------------------------------------------------------- /third-party-libs/vis/img/network/acceptDeleteIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chen0040/js-graph-algorithms/HEAD/third-party-libs/vis/img/network/acceptDeleteIcon.png -------------------------------------------------------------------------------- /test/quick-union-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Quick Union', function(){ 5 | it('should work as union find', function(){ 6 | var uf = new jsgraphs.QuickUnion(10); 7 | expect(uf.connected(0, 3)).to.equal(false); 8 | uf.union(0, 3); 9 | expect(uf.connected(0, 3)).to.equal(true); 10 | uf.union(0, 7); 11 | expect(uf.connected(0, 7)).to.equal(true); 12 | expect(uf.connected(3, 7)).to.equal(true); 13 | }); 14 | }); -------------------------------------------------------------------------------- /test/topological-sort-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Topological Sort', function(){ 5 | var dag = new jsgraphs.DiGraph(7); // must be directed acyclic graph 6 | 7 | dag.addEdge(0, 5); 8 | dag.addEdge(0, 2); 9 | dag.addEdge(0, 1); 10 | dag.addEdge(3, 6); 11 | dag.addEdge(3, 5); 12 | dag.addEdge(3, 4); 13 | dag.addEdge(5, 4); 14 | dag.addEdge(6, 4); 15 | dag.addEdge(6, 0); 16 | dag.addEdge(3, 2); 17 | dag.addEdge(1, 4); 18 | 19 | var ts = new jsgraphs.TopologicalSort(dag); 20 | 21 | it('should sort topoloically', function(){ 22 | var order = ts.order(); 23 | console.log(order); 24 | }); 25 | }); -------------------------------------------------------------------------------- /test/min-pq-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('MinPQ', function(){ 5 | it('should function as min priority queue', function(){ 6 | var pq = new jsgraphs.MinPQ(); 7 | 8 | pq.enqueue(10); 9 | pq.enqueue(9); 10 | pq.enqueue(7); 11 | pq.enqueue(8); 12 | pq.enqueue(3); 13 | pq.enqueue(4); 14 | pq.enqueue(5); 15 | pq.enqueue(2); 16 | pq.enqueue(1); 17 | pq.enqueue(6); 18 | 19 | expect(pq.isEmpty()).to.equal(false); 20 | for( var i = 1; i <= 10; ++i) { 21 | expect(pq.delMin()).to.equal(i); 22 | expect(pq.size()).to.equal(10 - i); 23 | } 24 | expect(pq.isEmpty()).to.equal(true); 25 | }); 26 | }); -------------------------------------------------------------------------------- /test/graph-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require("chai").expect; 2 | var jsgraphs = require("../src/jsgraphs"); 3 | 4 | describe("Create various types of Graphs", function() { 5 | describe("Create unweighted undirected graph", function() { 6 | var g = new jsgraphs.Graph(6); 7 | g.addEdge(0, 5); 8 | g.addEdge(2, 4); 9 | g.addEdge(2, 3); 10 | g.addEdge(1, 2); 11 | g.addEdge(0, 1); 12 | g.addEdge(3, 4); 13 | g.addEdge(3, 5); 14 | g.addEdge(0, 2); 15 | g.node(2).label = 'Hello'; 16 | g.edge(0, 2).label = 'World'; 17 | it("should has 6 vertices", function() { 18 | expect(g.V).to.equal(6); 19 | }); 20 | it("should be undirected", function() { 21 | expect(g.adj(0)).to.contains(5); 22 | expect(g.adj(5)).to.contains(0); 23 | }); 24 | }); 25 | 26 | 27 | 28 | }); -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // Load the plugin that provides the "uglify" task. 3 | grunt.loadNpmTasks('grunt-contrib-uglify'); 4 | grunt.loadNpmTasks('grunt-mocha-test'); 5 | grunt.loadNpmTasks('grunt-eslint'); 6 | 7 | grunt.initConfig({ 8 | pkg: grunt.file.readJSON('package.json'), 9 | uglify: { 10 | options: { 11 | preserveComments: 'some', 12 | }, 13 | build: { 14 | src: 'src/jsgraphs.js', 15 | dest: 'build/jsgraphs.min.js', 16 | }, 17 | }, 18 | mochaTest: { 19 | test: { 20 | options: { 21 | reporter: 'spec', 22 | }, 23 | src: ['tests/**/*.js'], 24 | }, 25 | }, 26 | }); 27 | 28 | // Default task(s). 29 | grunt.registerTask('default', ['uglify']); 30 | grunt.registerTask('test', ['mochaTest']); 31 | }; -------------------------------------------------------------------------------- /test/queue-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Queue operations', function() { 5 | it('should enqueue and dequeue correctly', function() { 6 | var queue = new jsgraphs.Queue(); 7 | queue.enqueue(10); 8 | queue.enqueue(20); 9 | queue.enqueue(30); 10 | var a = queue.toArray(); 11 | expect(a.length).to.equal(3); 12 | for(var i=0; i < a.length; ++i) { 13 | expect(a[i]).to.equal((i+1) * 10); 14 | } 15 | expect(queue.size()).to.equal(3); 16 | expect(queue.isEmpty()).to.equal(false); 17 | expect(queue.dequeue()).to.equal(10); 18 | expect(queue.dequeue()).to.equal(20); 19 | expect(queue.dequeue()).to.equal(30); 20 | expect(queue.isEmpty()).to.equal(true); 21 | }); 22 | }); -------------------------------------------------------------------------------- /test/connected-components-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Connected Components for undirected graph', function(){ 5 | var g = new jsgraphs.Graph(13); 6 | g.addEdge(0, 5); 7 | g.addEdge(4, 3); 8 | g.addEdge(0, 1); 9 | g.addEdge(9, 12); 10 | g.addEdge(6, 4); 11 | g.addEdge(5, 4); 12 | g.addEdge(0, 2); 13 | g.addEdge(11, 12); 14 | g.addEdge(9,10); 15 | g.addEdge(0, 6); 16 | g.addEdge(7, 8); 17 | g.addEdge(9, 11); 18 | g.addEdge(5, 3); 19 | 20 | it('should have three components', function(){ 21 | var cc = new jsgraphs.ConnectedComponents(g); 22 | expect(cc.componentCount()).to.equal(3); 23 | for (var v = 0; v < g.V; ++v) { 24 | console.log('id[' + v + ']: ' + cc.componentId(v)); 25 | } 26 | }); 27 | }); -------------------------------------------------------------------------------- /test/depth-first-search-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Depth first search', function(){ 5 | it('should traverse correctly', function(){ 6 | var g = new jsgraphs.Graph(6); 7 | g.addEdge(0, 5); 8 | g.addEdge(2, 4); 9 | g.addEdge(2, 3); 10 | g.addEdge(1, 2); 11 | g.addEdge(0, 1); 12 | g.addEdge(3, 4); 13 | g.addEdge(3, 5); 14 | g.addEdge(0, 2); 15 | var s = 0; 16 | var dfs = new jsgraphs.DepthFirstSearch(g, s); 17 | 18 | 19 | for(var v=0; v < g.V; ++v) { 20 | if(dfs.hasPathTo(v)) { 21 | console.log(s + " is connected to " + v); 22 | console.log("path: " + dfs.pathTo(v)); 23 | } else { 24 | console.log('No path from ' + s + ' to ' + v); 25 | } 26 | } 27 | }); 28 | }); -------------------------------------------------------------------------------- /test/breadth-first-search-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Depth first search', function(){ 5 | it('should traverse correctly', function(){ 6 | var g = new jsgraphs.Graph(6); 7 | g.addEdge(0, 5); 8 | g.addEdge(2, 4); 9 | g.addEdge(2, 3); 10 | g.addEdge(1, 2); 11 | g.addEdge(0, 1); 12 | g.addEdge(3, 4); 13 | g.addEdge(3, 5); 14 | g.addEdge(0, 2); 15 | var s = 0; 16 | var bfs = new jsgraphs.BreadthFirstSearch(g, s); 17 | 18 | 19 | for(var v=0; v < g.V; ++v) { 20 | if(bfs.hasPathTo(v)) { 21 | console.log(s + " is connected to " + v); 22 | console.log("path: " + bfs.pathTo(v)); 23 | } else { 24 | console.log('No path from ' + s + ' to ' + v); 25 | } 26 | } 27 | }); 28 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Xianshun Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/index-min-pq-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Index MinPQ', function(){ 5 | it('should check if index exists in pq and determines where to insert', function(){ 6 | var pq = new jsgraphs.IndexMinPQ(100); 7 | expect(pq.containsIndex(10)).to.equal(false); 8 | pq.insert(10, 12.0); 9 | expect(pq.containsIndex(10)).to.equal(true); 10 | pq.insert(9, 14.0); 11 | expect(pq.min()).to.equal(10); 12 | expect(pq.containsIndex(9)).to.equal(true); 13 | expect(pq.minKey()).to.equal(12.0); 14 | pq.decreaseKey(10, 13.0); 15 | expect(pq.minKey()).to.equal(12.0); 16 | pq.decreaseKey(10, 11.0); 17 | expect(pq.minKey()).to.equal(11.0); 18 | pq.decreaseKey(9, 10.0); 19 | expect(pq.minKey()).to.equal(10.0); 20 | expect(pq.min()).to.equal(9); 21 | expect(pq.size()).to.equal(2); 22 | expect(pq.isEmpty()).to.equal(false); 23 | expect(pq.delMin()).to.equal(9); 24 | expect(pq.delMin()).to.equal(10); 25 | expect(pq.isEmpty()).to.equal(true); 26 | }); 27 | }); -------------------------------------------------------------------------------- /test/directed-graph-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require("chai").expect; 2 | var jsgraphs = require("../src/jsgraphs"); 3 | 4 | describe("Create various types of DiGraph", function() { 5 | describe("Create unweighted directed graph", function() { 6 | var g = new jsgraphs.DiGraph(13); 7 | g.addEdge(4, 2); 8 | g.addEdge(2, 3); 9 | g.addEdge(3, 2); 10 | g.addEdge(6, 0); 11 | g.addEdge(0, 1); 12 | g.addEdge(2, 0); 13 | g.addEdge(11, 12); 14 | g.addEdge(12, 9); 15 | g.addEdge(9, 10); 16 | g.addEdge(9, 11); 17 | g.addEdge(7, 9); 18 | g.addEdge(10, 12); 19 | g.addEdge(11, 4); 20 | g.addEdge(4, 3); 21 | g.addEdge(3, 5); 22 | g.addEdge(6, 8); 23 | g.addEdge(8, 6); 24 | g.addEdge(5, 4); 25 | g.addEdge(0, 5); 26 | g.addEdge(6, 4); 27 | g.addEdge(6, 9); 28 | g.addEdge(7, 6); 29 | 30 | g.edge(2, 0).label = 'World'; 31 | it("should has 13 vertices", function() { 32 | expect(g.V).to.equal(13); 33 | }); 34 | it("should be directed", function() { 35 | expect(g.adj(4)).to.contains(2); 36 | expect(g.adj(2)).not.to.contains(4); 37 | }); 38 | }); 39 | 40 | 41 | 42 | }); -------------------------------------------------------------------------------- /test/stack-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Stack operations', function(){ 5 | describe('Stack push and pop', function(){ 6 | 7 | 8 | it('should be able to push, peep and pop', function(){ 9 | var stack = new jsgraphs.Stack(); 10 | stack.push(10); 11 | expect(stack.size()).to.equal(1); 12 | expect(stack.peep()).to.equal(10); 13 | expect(stack.pop()).to.equal(10); 14 | expect(stack.size()).to.equal(0); 15 | expect(stack.isEmpty()).to.equal(true); 16 | for(var i = 0; i < 100; ++i) { 17 | stack.push(i); 18 | expect(stack.size()).to.equal(i+1); 19 | } 20 | var a = stack.toArray(); 21 | for(var i = 0; i < 100; ++i) { 22 | expect(a[i]).to.equal(100 - i - 1); 23 | } 24 | 25 | for(var i = 0; i < 100; ++i) { 26 | expect(stack.pop()).to.equal(100 - i - 1); 27 | expect(stack.size()).to.equal(100 -i - 1); 28 | } 29 | 30 | }); 31 | }); 32 | }); -------------------------------------------------------------------------------- /test/strongly-connected-components-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Strongly Connected Components for directed graphs', function(){ 5 | var graph = new jsgraphs.DiGraph(13); 6 | graph.addEdge(4, 2); 7 | graph.addEdge(2, 3); 8 | graph.addEdge(3, 2); 9 | graph.addEdge(6, 0); 10 | graph.addEdge(0, 1); 11 | graph.addEdge(2, 0); 12 | graph.addEdge(11, 12); 13 | graph.addEdge(12, 9); 14 | graph.addEdge(9, 10); 15 | graph.addEdge(9, 11); 16 | graph.addEdge(8, 9); 17 | graph.addEdge(10, 12); 18 | graph.addEdge(11, 4); 19 | graph.addEdge(4, 3); 20 | graph.addEdge(3, 5); 21 | graph.addEdge(7, 8); 22 | graph.addEdge(8, 7); 23 | graph.addEdge(5, 4); 24 | graph.addEdge(0, 5); 25 | graph.addEdge(6, 4); 26 | graph.addEdge(6, 9); 27 | graph.addEdge(7, 6); 28 | 29 | it('should have five components', function(){ 30 | var scc = new jsgraphs.StronglyConnectedComponents(graph); 31 | expect(scc.componentCount()).to.equal(5); 32 | for (var v = 0; v < graph.V; ++v) { 33 | console.log('id[' + v + ']: ' + scc.componentId(v)); 34 | } 35 | }); 36 | }); -------------------------------------------------------------------------------- /test/flow-network-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Flow Network', function(){ 5 | it('should confirms to flow edge spec', function(){ 6 | var g = new jsgraphs.FlowNetwork(8); 7 | g.addEdge(new jsgraphs.FlowEdge(0, 1, 10)); 8 | g.addEdge(new jsgraphs.FlowEdge(0, 2, 5)); 9 | g.addEdge(new jsgraphs.FlowEdge(0, 3, 15)); 10 | g.addEdge(new jsgraphs.FlowEdge(1, 4, 9)); 11 | g.addEdge(new jsgraphs.FlowEdge(1, 5, 15)); 12 | g.addEdge(new jsgraphs.FlowEdge(1, 2, 4)); 13 | g.addEdge(new jsgraphs.FlowEdge(2, 5, 8)); 14 | g.addEdge(new jsgraphs.FlowEdge(2, 3, 4)); 15 | g.addEdge(new jsgraphs.FlowEdge(3, 6, 16)); 16 | g.addEdge(new jsgraphs.FlowEdge(4, 5, 15)); 17 | g.addEdge(new jsgraphs.FlowEdge(4, 7, 10)); 18 | g.addEdge(new jsgraphs.FlowEdge(5, 7, 10)); 19 | g.addEdge(new jsgraphs.FlowEdge(5, 6, 15)); 20 | g.addEdge(new jsgraphs.FlowEdge(6, 2, 6)); 21 | g.addEdge(new jsgraphs.FlowEdge(6, 7, 10)); 22 | 23 | expect(g.V).to.equal(8); 24 | 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(30); 31 | }); 32 | }); -------------------------------------------------------------------------------- /test/weighted-digraph-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Weigthed Directed Graph', function(){ 5 | it('should be weighted and directed', 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 | g.node(4).label = 'Hello'; 25 | g.edge(4, 5).label = 'World'; 26 | 27 | expect(g.V).to.equal(8); 28 | var edgeCount = 0; 29 | for(var v = 0; v < g.V; ++v){ 30 | var adj_v = g.adj(v); 31 | edgeCount += adj_v.length; 32 | } 33 | expect(edgeCount).to.equal(16); 34 | }); 35 | }); -------------------------------------------------------------------------------- /test/kruskal-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Kruskal Minimum Spanning Tree', function(){ 5 | it('should generate the minimum spanning tree', function(){ 6 | var g = new jsgraphs.WeightedGraph(8); 7 | 8 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 9 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 10 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 11 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 12 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 13 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 14 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 15 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 16 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 17 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 18 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 19 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 20 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 21 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 22 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 23 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 24 | 25 | var kruskal = new jsgraphs.KruskalMST(g); 26 | var mst = kruskal.mst; 27 | for(var i=0; i < mst.length; ++i) { 28 | var e = mst[i]; 29 | var v = e.either(); 30 | var w = e.other(v); 31 | console.log('(' + v + ', ' + w + '): ' + e.weight); 32 | } 33 | }); 34 | }); -------------------------------------------------------------------------------- /test/lazy-prim-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Lazy Prim Minimum Spanning Tree', function(){ 5 | it('should generate the minimum spanning tree', function(){ 6 | var g = new jsgraphs.WeightedGraph(8); 7 | 8 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 9 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 10 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 11 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 12 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 13 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 14 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 15 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 16 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 17 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 18 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 19 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 20 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 21 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 22 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 23 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 24 | 25 | var prim = new jsgraphs.LazyPrimMST(g); 26 | var mst = prim.mst; 27 | for(var i=0; i < mst.length; ++i) { 28 | var e = mst[i]; 29 | var v = e.either(); 30 | var w = e.other(v); 31 | console.log('(' + v + ', ' + w + '): ' + e.weight); 32 | } 33 | }); 34 | }); -------------------------------------------------------------------------------- /test/eager-prim-mst-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Eager Prim Minimum Spanning Tree', function(){ 5 | it('should generate the minimum spanning tree', function(){ 6 | var g = new jsgraphs.WeightedGraph(8); 7 | 8 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 9 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 10 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 11 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 12 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 13 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 14 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 15 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 16 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 17 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 18 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 19 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 20 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 21 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 22 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 23 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 24 | 25 | var prim = new jsgraphs.EagerPrimMST(g); 26 | var mst = prim.mst; 27 | for(var i=0; i < mst.length; ++i) { 28 | var e = mst[i]; 29 | var v = e.either(); 30 | var w = e.other(v); 31 | console.log('(' + v + ', ' + w + '): ' + e.weight); 32 | } 33 | }); 34 | }); -------------------------------------------------------------------------------- /test/ford-fulkerson-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('MaxFlow-MinCut', function(){ 5 | it('should work', function(){ 6 | var g = new jsgraphs.FlowNetwork(8); 7 | g.addEdge(new jsgraphs.FlowEdge(0, 1, 10)); 8 | g.addEdge(new jsgraphs.FlowEdge(0, 2, 5)); 9 | g.addEdge(new jsgraphs.FlowEdge(0, 3, 15)); 10 | g.addEdge(new jsgraphs.FlowEdge(1, 4, 9)); 11 | g.addEdge(new jsgraphs.FlowEdge(1, 5, 15)); 12 | g.addEdge(new jsgraphs.FlowEdge(1, 2, 4)); 13 | g.addEdge(new jsgraphs.FlowEdge(2, 5, 8)); 14 | g.addEdge(new jsgraphs.FlowEdge(2, 3, 4)); 15 | g.addEdge(new jsgraphs.FlowEdge(3, 6, 16)); 16 | g.addEdge(new jsgraphs.FlowEdge(4, 5, 15)); 17 | g.addEdge(new jsgraphs.FlowEdge(4, 7, 10)); 18 | g.addEdge(new jsgraphs.FlowEdge(5, 7, 10)); 19 | g.addEdge(new jsgraphs.FlowEdge(5, 6, 15)); 20 | g.addEdge(new jsgraphs.FlowEdge(6, 2, 6)); 21 | g.addEdge(new jsgraphs.FlowEdge(6, 7, 10)); 22 | 23 | g.node(2).label = 'Hello'; 24 | g.edge(0, 1).label = 'World'; 25 | 26 | var source = 0; 27 | var target = 7; 28 | var ff = new jsgraphs.FordFulkerson(g, source, target); 29 | console.log('max-flow: ' + ff.value); 30 | expect(ff.value).to.equal(28); 31 | 32 | var minCut = ff.minCut(g); 33 | 34 | for(var i = 0; i < minCut.length; ++i) { 35 | var e = minCut[i]; 36 | console.log('min-cut: (' + e.from() + ", " + e.to() + ')'); 37 | } 38 | 39 | }); 40 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-graph-algorithms", 3 | "version": "1.0.18", 4 | "description": "Package implements data structures and algorithms for processing various types of graphs", 5 | "author": "Xianshun Chen", 6 | "contributors": [ 7 | "Xianshun Chen " 8 | ], 9 | "license": "MIT", 10 | "main": "index.js", 11 | "typings": "src/jsgraphs.d.ts", 12 | "directories": { 13 | "test": "test" 14 | }, 15 | "scripts": { 16 | "test": "mocha test", 17 | "cover": "istanbul cover _mocha", 18 | "coveralls": "npm run cover -- --report lcovonly && cat ./coverage/lcov.info | coveralls" 19 | }, 20 | "bin": { 21 | "js-graphs": "./src/jsgraphs.js" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/chen0040/js-graph-algorithms.git" 26 | }, 27 | "keywords": [ 28 | "graph", 29 | "weighted graph", 30 | "digraph", 31 | "directed graph", 32 | "connected components", 33 | "strongly connected components", 34 | "min cut", 35 | "max flow", 36 | "dijkstra", 37 | "bellman-ford", 38 | "minimum spanning tree", 39 | "depth first search", 40 | "breadth first search", 41 | "directed cycles", 42 | "topological sort", 43 | "ford-fulkerson", 44 | "prim", 45 | "kruskal" 46 | ], 47 | "dependencies": { 48 | 49 | }, 50 | "devDependencies": { 51 | "chai": "^3.5.0", 52 | "coveralls": "^2.13.1", 53 | "grunt": "^1.0.1", 54 | "grunt-contrib-uglify": "^3.0.0", 55 | "grunt-eslint": "^19.0.0", 56 | "grunt-mocha-test": "^0.13.2", 57 | "istanbul": "^0.4.5", 58 | "mocha": "^3.4.1" 59 | }, 60 | "bugs": { 61 | "url": "https://github.com/chen0040/js-graph-algorithms/issues" 62 | }, 63 | "homepage": "https://github.com/chen0040/js-graph-algorithms#readme" 64 | } 65 | -------------------------------------------------------------------------------- /test/bellman-ford-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Bellman Ford', function(){ 5 | it('should get shortest path from Weigthed Directed 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 bf = new jsgraphs.BellmanFord(g, 0); 33 | 34 | for(var v = 1; v < g.V; ++v){ 35 | if(bf.hasPathTo(v)){ 36 | var path = bf.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: ' + bf.distanceTo(v) + '========='); 44 | } 45 | } 46 | }); 47 | }); -------------------------------------------------------------------------------- /test/dijkstra-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var jsgraphs = require('../src/jsgraphs'); 3 | 4 | describe('Dijkstra', function(){ 5 | it('should get shortest path from Weigthed Directed 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 dijkstra = new jsgraphs.Dijkstra(g, 0); 33 | 34 | for(var v = 1; v < g.V; ++v){ 35 | if(dijkstra.hasPathTo(v)){ 36 | var path = dijkstra.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: ' + dijkstra.distanceTo(v) + '========='); 44 | } 45 | } 46 | }); 47 | }); -------------------------------------------------------------------------------- /test/weighted-graph-spec.js: -------------------------------------------------------------------------------- 1 | var expect = require("chai").expect; 2 | var jsgraphs = require("../src/jsgraphs"); 3 | 4 | describe("Create various types of Weighted Graphs", function() { 5 | describe("Create weighted undirected graph", function() { 6 | var g = new jsgraphs.WeightedGraph(8); 7 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 8 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 9 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 10 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 11 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 12 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 13 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 14 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 15 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 16 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 17 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 18 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 19 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 20 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 21 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 22 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 23 | 24 | g.node(4).label = 'Hello'; 25 | g.edge(4, 5).label = 'World'; 26 | 27 | it("should has 8 vertices", function() { 28 | expect(g.V).to.equal(8); 29 | }); 30 | it("should be undirected", function() { 31 | var adj_v = g.adj(0); 32 | for (var i = 0; i < adj_v.length; ++i) { 33 | var e = adj_v[i]; 34 | var w = e.other(0); 35 | var adj_w = g.adj(w); 36 | 37 | var found = false; 38 | for (var j = 0; j < adj_w.length; ++j) { 39 | var e2 = adj_w[j]; 40 | if(e2.other(w) == 0){ 41 | found = true; 42 | } 43 | } 44 | 45 | expect(found).to.equal(true); 46 | } 47 | 48 | var edgeCount = 0; 49 | for (var v = 0; v < g.V; ++v) { 50 | edgeCount+=g.adj(v).length; 51 | } 52 | expect(edgeCount).to.equal(32); 53 | }); 54 | }); 55 | 56 | 57 | 58 | }); -------------------------------------------------------------------------------- /test/topoloical-sort-shortest-paths-spec.js: -------------------------------------------------------------------------------- 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 | }); -------------------------------------------------------------------------------- /examples/example-graph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Graph

13 |
14 | 15 | 65 | 66 | -------------------------------------------------------------------------------- /examples/example-dfs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Depth First Search on Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Depth First Search on Graph

13 |
14 | 15 | 78 | 79 | -------------------------------------------------------------------------------- /examples/example-digraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DiGraph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Directed Graph

13 |
14 | 15 | 79 | 80 | -------------------------------------------------------------------------------- /examples/example-connected-components.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Connected Components on Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Connected Components on Graph

13 |
14 | 15 | 77 | 78 | -------------------------------------------------------------------------------- /examples/example-weighted-digraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Weighted DiGraph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Weighted DiGraph

13 |
14 | 15 | 76 | 77 | -------------------------------------------------------------------------------- /examples/example-strongly-connected-components.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Strongly Connected Components on Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Strongly Connected Components on Graph

13 |
14 | 15 | 85 | 86 | -------------------------------------------------------------------------------- /examples/example-weighted-graph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Weighted Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Weighted Graph

13 |
14 | 15 | 76 | 77 | -------------------------------------------------------------------------------- /examples/example-topo-sort.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Topological Sort on Directed Acyclic Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Topological Sort on Directed Acyclic Graph

13 |
14 | 15 | 96 | 97 | -------------------------------------------------------------------------------- /examples/example-kruskal.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Minimum Spanning Tree Weighted Graph (Kruskal) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Minimum Spanning Tree Weighted Graph (Kruskal)

13 |
14 | 15 | 102 | 103 | -------------------------------------------------------------------------------- /examples/example-lazy-prim.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Minimum Spanning Tree Weighted Graph (Lazy Prim) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Minimum Spanning Tree Weighted Graph (Lazy Prim)

13 |
14 | 15 | 102 | 103 | -------------------------------------------------------------------------------- /examples/example-eager-prim.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Minimum Spanning Tree Weighted Graph (Eager Prim) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Minimum Spanning Tree Weighted Graph (Eager Prim)

13 |
14 | 15 | 102 | 103 | -------------------------------------------------------------------------------- /examples/example-ford-fulkerson.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MaxFlow-MinCut (Ford-Fulkerson) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

MaxFlow-MinCut (Ford-Fulkerson)

13 |
14 | 15 | 105 | 106 | -------------------------------------------------------------------------------- /examples/example-dijkstra.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Weighted DiGraph 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Weighted DiGraph

13 |
14 | 15 | 104 | 105 | -------------------------------------------------------------------------------- /src/jsgraphs.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace JsGraphs { 2 | interface Node { 3 | label?: string; 4 | } 5 | class StackNode { 6 | value: T; 7 | next: StackNode | null; 8 | constructor(value: T); 9 | } 10 | class Stack { 11 | private N; 12 | private first; 13 | constructor(); 14 | push(a: T): void; 15 | _push(x: StackNode | null, a: T): StackNode; 16 | pop(): T | undefined; 17 | size(): number; 18 | isEmpty(): boolean; 19 | peep(): T | undefined; 20 | toArray(): T[]; 21 | } 22 | class QueueNode { 23 | value: T; 24 | next: QueueNode | null; 25 | constructor(a: T); 26 | } 27 | class Queue { 28 | private first; 29 | private last; 30 | private N; 31 | constructor(); 32 | enqueue(item: T): void; 33 | dequeue(): T | undefined; 34 | size(): number; 35 | isEmpty(): boolean; 36 | toArray(): T[]; 37 | } 38 | class MinPQ { 39 | private s; 40 | private N; 41 | private compare; 42 | constructor(compare?: (a1: any, a2: any) => number); 43 | enqueue(item: T): void; 44 | swim(k: number): void; 45 | delMin(): T | undefined; 46 | sink(k: number): void; 47 | size(): number; 48 | isEmpty(): boolean; 49 | } 50 | class QuickUnion { 51 | private id; 52 | constructor(V: number); 53 | union(v: number, w: number): void; 54 | root(q: number): number; 55 | connected(v: number, w: number): boolean; 56 | } 57 | class IndexMinPQ { 58 | private keys; 59 | private pq; 60 | private qp; 61 | private N; 62 | private compare; 63 | constructor(N: number, compare?: (a1: any, a2: any) => number); 64 | insert(index: number, key: T): void; 65 | decreaseKey(index: number, key: T): void; 66 | minKey(): T | null; 67 | min(): number; 68 | delMin(): number; 69 | swim(k: number): void; 70 | sink(k: number): void; 71 | containsIndex(index: number): boolean; 72 | isEmpty(): boolean; 73 | size(): number; 74 | } 75 | class Graph { 76 | V: number; 77 | private adjList; 78 | private nodeInfo; 79 | private edges; 80 | constructor(V: number); 81 | addEdge(v: number, w: number): void; 82 | adj(v: number): number[]; 83 | node(v: number): Node; 84 | edge(v: number, w: number): Edge | null; 85 | } 86 | class DiGraph { 87 | V: number; 88 | private adjList; 89 | private nodeInfo; 90 | private edges; 91 | constructor(V: number); 92 | addEdge(v: number, w: number): void; 93 | edge(v: number, w: number): Edge | null; 94 | adj(v: number): number[]; 95 | node(v: number): Node; 96 | reverse(): DiGraph; 97 | } 98 | class Edge { 99 | private v; 100 | private w; 101 | weight: number; 102 | label?: string; 103 | constructor(v: number, w: number, weight: number); 104 | either(): number; 105 | other(x: number): number; 106 | from(): number; 107 | to(): number; 108 | } 109 | class WeightedGraph { 110 | V: number; 111 | protected adjList: Edge[][]; 112 | private nodeInfo; 113 | constructor(V: number); 114 | adj(v: number): Edge[]; 115 | edge(v: number, w: number): Edge | null; 116 | node(v: number): Node; 117 | addEdge(e: Edge): void; 118 | } 119 | class WeightedDiGraph extends WeightedGraph { 120 | addEdge(e: Edge): void; 121 | edge(v: number, w: number): Edge | null; 122 | toDiGraph(): DiGraph; 123 | } 124 | class FlowEdge { 125 | private v; 126 | private w; 127 | private capacity; 128 | private flow; 129 | label?: string; 130 | constructor(v: number, w: number, capacity: number); 131 | residualCapacityTo(x: number): number; 132 | addResidualFlowTo(x: number, deltaFlow: number): void; 133 | from(): number; 134 | to(): number; 135 | other(x: number): number; 136 | } 137 | class FlowNetwork { 138 | V: number; 139 | private adjList; 140 | private nodeInfo; 141 | constructor(V: number); 142 | node(v: number): Node; 143 | edge(v: number, w: number): FlowEdge | null; 144 | addEdge(e: FlowEdge): void; 145 | adj(v: number): FlowEdge[]; 146 | } 147 | class DepthFirstSearch { 148 | private s; 149 | private marked; 150 | private edgeTo; 151 | constructor(G: Graph, s: number); 152 | dfs(G: Graph, v: number): void; 153 | hasPathTo(v: number): boolean; 154 | pathTo(v: number): number[]; 155 | } 156 | class BreadthFirstSearch { 157 | private V; 158 | private s; 159 | private marked; 160 | private edgeTo; 161 | constructor(G: Graph, s: number); 162 | hasPathTo(v: number): boolean; 163 | pathTo(v: number): number[]; 164 | } 165 | class ConnectedComponents { 166 | private count; 167 | private marked; 168 | private id; 169 | constructor(G: Graph); 170 | dfs(G: Graph, v: number): void; 171 | componentId(v: number): number; 172 | componentCount(): number; 173 | } 174 | class TopologicalSort { 175 | private postOrder; 176 | private marked; 177 | constructor(G: DiGraph); 178 | dfs(G: DiGraph, v: number): void; 179 | order(): number[]; 180 | } 181 | class StronglyConnectedComponents { 182 | private count; 183 | private marked; 184 | private id; 185 | constructor(G: DiGraph); 186 | dfs(G: DiGraph, v: number): void; 187 | componentId(v: number): number; 188 | componentCount(): number; 189 | } 190 | class KruskalMST { 191 | mst: Edge[]; 192 | constructor(G: WeightedGraph); 193 | } 194 | class LazyPrimMST { 195 | mst: Edge[]; 196 | private marked; 197 | private pq; 198 | constructor(G: WeightedGraph); 199 | visit(G: WeightedGraph, v: number): void; 200 | } 201 | class EagerPrimMST { 202 | mst: Edge[]; 203 | private pq; 204 | private marked; 205 | constructor(G: WeightedGraph); 206 | visit(G: WeightedGraph, v: number): void; 207 | } 208 | class Dijkstra { 209 | private s; 210 | private marked; 211 | private edgeTo; 212 | private cost; 213 | private pq; 214 | constructor(G: WeightedGraph, s: number); 215 | relax(e: Edge): void; 216 | hasPathTo(v: number): boolean; 217 | pathTo(v: number): Edge[]; 218 | distanceTo(v: number): number; 219 | } 220 | class BellmanFord { 221 | private s; 222 | private marked; 223 | private edgeTo; 224 | private cost; 225 | constructor(G: WeightedGraph, s: number); 226 | relax(e: Edge): void; 227 | hasPathTo(v: number): boolean; 228 | pathTo(v: number): Edge[]; 229 | distanceTo(v: number): number; 230 | } 231 | class TopologicalSortShortestPaths { 232 | private s; 233 | private marked; 234 | private edgeTo; 235 | private cost; 236 | constructor(G: WeightedDiGraph, s: number); 237 | relax(e: Edge): void; 238 | hasPathTo(v: number): boolean; 239 | pathTo(v: number): Edge[]; 240 | distanceTo(v: number): number; 241 | } 242 | class FordFulkerson { 243 | value: number; 244 | private marked; 245 | private edgeTo; 246 | private s; 247 | private t; 248 | constructor(G: FlowNetwork, s: number, t: number); 249 | hasAugmentedPath(G: FlowNetwork): boolean; 250 | minCut(G: FlowNetwork): FlowEdge[]; 251 | } 252 | } 253 | 254 | declare module "js-graph-algorithms" { 255 | export = JsGraphs; 256 | } 257 | -------------------------------------------------------------------------------- /third-party-libs/vis/vis-network.min.css: -------------------------------------------------------------------------------- 1 | .vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper::after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:rgba(0,0,0,0);width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%)}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5}div.vis-color-picker{position:absolute;top:0;left:30px;margin-top:-140px;margin-left:30px;width:310px;height:444px;z-index:1;padding:10px;border-radius:15px;background-color:#fff;display:none;box-shadow:rgba(0,0,0,.5) 0 0 10px 0}div.vis-color-picker div.vis-arrow{position:absolute;top:147px;left:5px}div.vis-color-picker div.vis-arrow::after,div.vis-color-picker div.vis-arrow::before{right:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.vis-color-picker div.vis-arrow:after{border-color:rgba(255,255,255,0);border-right-color:#fff;border-width:30px;margin-top:-30px}div.vis-color-picker div.vis-color{position:absolute;width:289px;height:289px;cursor:pointer}div.vis-color-picker div.vis-brightness{position:absolute;top:313px}div.vis-color-picker div.vis-opacity{position:absolute;top:350px}div.vis-color-picker div.vis-selector{position:absolute;top:137px;left:137px;width:15px;height:15px;border-radius:15px;border:1px solid #fff;background:#4c4c4c;background:-moz-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4c4c4c),color-stop(12%,#595959),color-stop(25%,#666),color-stop(39%,#474747),color-stop(50%,#2c2c2c),color-stop(51%,#000),color-stop(60%,#111),color-stop(76%,#2b2b2b),color-stop(91%,#1c1c1c),color-stop(100%,#131313));background:-webkit-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-o-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-ms-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:linear-gradient(to bottom,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%)}div.vis-color-picker div.vis-new-color{position:absolute;width:140px;height:20px;border:1px solid rgba(0,0,0,.1);border-radius:5px;top:380px;left:159px;text-align:right;padding-right:2px;font-size:10px;color:rgba(0,0,0,.4);vertical-align:middle;line-height:20px}div.vis-color-picker div.vis-initial-color{position:absolute;width:140px;height:20px;border:1px solid rgba(0,0,0,.1);border-radius:5px;top:380px;left:10px;text-align:left;padding-left:2px;font-size:10px;color:rgba(0,0,0,.4);vertical-align:middle;line-height:20px}div.vis-color-picker div.vis-label{position:absolute;width:300px;left:10px}div.vis-color-picker div.vis-label.vis-brightness{top:300px}div.vis-color-picker div.vis-label.vis-opacity{top:338px}div.vis-color-picker div.vis-button{position:absolute;width:68px;height:25px;border-radius:10px;vertical-align:middle;text-align:center;line-height:25px;top:410px;border:2px solid #d9d9d9;background-color:#f7f7f7;cursor:pointer}div.vis-color-picker div.vis-button.vis-cancel{left:5px}div.vis-color-picker div.vis-button.vis-load{left:82px}div.vis-color-picker div.vis-button.vis-apply{left:159px}div.vis-color-picker div.vis-button.vis-save{left:236px}div.vis-color-picker input.vis-range{width:290px;height:20px}div.vis-network div.vis-manipulation{box-sizing:content-box;border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);padding-top:4px;position:absolute;left:0;top:0;width:100%;height:28px}div.vis-network div.vis-edit-mode{position:absolute;left:0;top:5px;height:30px}div.vis-network div.vis-close{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-repeat:no-repeat;background-image:url(img/network/cross.png);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-close:hover{opacity:.6}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button{float:left;font-family:verdana;font-size:12px;-moz-border-radius:15px;border-radius:15px;display:inline-block;background-position:0 0;background-repeat:no-repeat;height:24px;margin-left:10px;cursor:pointer;padding:0 8px 0 8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-manipulation div.vis-button:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.vis-network div.vis-manipulation div.vis-button:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.vis-network div.vis-manipulation div.vis-button.vis-back{background-image:url(img/network/backIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.vis-network div.vis-manipulation div.vis-button.vis-none:active{box-shadow:1px 1px 8px transparent}div.vis-network div.vis-manipulation div.vis-button.vis-none{padding:0}div.vis-network div.vis-manipulation div.notification{margin:2px;font-weight:700}div.vis-network div.vis-manipulation div.vis-button.vis-add{background-image:url(img/network/addNodeIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit,div.vis-network div.vis-manipulation div.vis-button.vis-edit{background-image:url(img/network/editIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode{background-color:#fcfcfc;border:1px solid #ccc}div.vis-network div.vis-manipulation div.vis-button.vis-connect{background-image:url(img/network/connectIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-delete{background-image:url(img/network/deleteIcon.png)}div.vis-network div.vis-edit-mode div.vis-label,div.vis-network div.vis-manipulation div.vis-label{margin:0 0 0 23px;line-height:25px}div.vis-network div.vis-manipulation div.vis-separator-line{float:left;display:inline-block;width:1px;height:21px;background-color:#bdbdbd;margin:0 7px 0 15px}div.vis-network div.vis-navigation div.vis-button{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;display:inline-block;background-position:2px 2px;background-repeat:no-repeat;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-navigation div.vis-button:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.vis-network div.vis-navigation div.vis-button:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.vis-network div.vis-navigation div.vis-button.vis-up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.vis-network div.vis-navigation div.vis-button.vis-right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.vis-network div.vis-navigation div.vis-button.vis-zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.vis-network div.vis-navigation div.vis-button.vis-zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px} -------------------------------------------------------------------------------- /third-party-libs/vis/vis-timeline-graph2d.min.css: -------------------------------------------------------------------------------- 1 | .vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper::after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:rgba(0,0,0,0);width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%)}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5}.vis-current-time{background-color:#ff7f6e;width:2px;z-index:1;pointer-events:none}.vis-rolling-mode-btn{height:40px;width:40px;position:absolute;top:7px;right:20px;border-radius:50%;font-size:28px;cursor:pointer;opacity:.8;color:#fff;font-weight:700;text-align:center;background:#3876c2}.vis-rolling-mode-btn:before{content:"\26F6"}.vis-rolling-mode-btn:hover{opacity:1}.vis-custom-time{background-color:#6e94ff;width:2px;cursor:move;z-index:1}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis-legend-text{white-space:nowrap;display:inline-block}.vis-item{position:absolute;color:#1a1a1a;border-color:#97b0f8;border-width:1px;background-color:#d5ddf6;display:inline-block;z-index:1}.vis-item.vis-selected{border-color:#ffc200;background-color:#fff785;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-point.vis-selected{background-color:#fff785}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:0 0}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item-visible-frame{white-space:nowrap}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-onUpdateTime-tooltip{position:absolute;background:#4f81bd;color:#fff;width:200px;text-align:center;white-space:nowrap;padding:5px;border-radius:1px;transition:.4s;-o-transition:.4s;-moz-transition:.4s;-webkit-transition:.4s}.vis-item .vis-delete,.vis-item .vis-delete-rtl{position:absolute;top:0;width:24px;height:24px;box-sizing:border-box;padding:0 5px;cursor:pointer;-webkit-transition:background .2s linear;-moz-transition:background .2s linear;-ms-transition:background .2s linear;-o-transition:background .2s linear;transition:background .2s linear}.vis-item .vis-delete{right:-24px}.vis-item .vis-delete-rtl{left:-24px}.vis-item .vis-delete-rtl:after,.vis-item .vis-delete:after{content:"\00D7";color:red;font-family:arial,sans-serif;font-size:22px;font-weight:700;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear}.vis-item .vis-delete-rtl:hover,.vis-item .vis-delete:hover{background:red}.vis-item .vis-delete-rtl:hover:after,.vis-item .vis-delete:hover:after{color:#fff}.vis-item .vis-drag-center{position:absolute;width:100%;height:100%;top:0;left:0;cursor:move}.vis-item.vis-range .vis-drag-left{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;right:-4px;cursor:e-resize}.vis-range.vis-item.vis-readonly .vis-drag-left,.vis-range.vis-item.vis-readonly .vis-drag-right{cursor:auto}.vis-itemset{position:relative;padding:0;margin:0;box-sizing:border-box}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-nested-group{background:#f5f5f5}.vis-label.vis-nesting-group.expanded:before{content:"\25BC"}.vis-label.vis-nesting-group.collapsed-rtl:before{content:"\25C0"}.vis-label.vis-nesting-group.collapsed:before{content:"\25B6"}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-labelset{position:relative;overflow:hidden;box-sizing:border-box}.vis-labelset .vis-label{position:relative;left:0;top:0;width:100%;color:#4d4d4d;box-sizing:border-box}.vis-labelset .vis-label{border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}.vis-panel{position:absolute;padding:0;margin:0;box-sizing:border-box}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}.vis-time-axis{position:relative;overflow:hidden}.vis-time-axis.vis-foreground{top:0;left:0;width:100%}.vis-time-axis.vis-background{position:absolute;top:0;left:0;width:100%;height:100%}.vis-time-axis .vis-text{position:absolute;color:#4d4d4d;padding:3px;overflow:hidden;box-sizing:border-box;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{position:absolute;border-left:1px solid}.vis-time-axis .vis-grid.vis-vertical-rtl{position:absolute;border-right:1px solid}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}.vis-timeline{position:relative;border:1px solid #bfbfbf;overflow:hidden;padding:0;margin:0;box-sizing:border-box} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-graph-algorithms 2 | Package provides javascript implementation of algorithms for graph processing 3 | 4 | [![Build Status](https://travis-ci.org/chen0040/js-graph-algorithms.svg?branch=master)](https://travis-ci.org/chen0040/js-graph-algorithms) [![Coverage Status](https://coveralls.io/repos/github/chen0040/js-graph-algorithms/badge.svg?branch=master)](https://coveralls.io/github/chen0040/js-graph-algorithms?branch=master) 5 | 6 | # Features 7 | 8 | * Depth First Search (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-dfs.html)) 9 | * Breadth First Search 10 | * Connected Components for undirected graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-connected-components.html)) 11 | * Topoloical Sort (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-topo-sort.html)) 12 | * Strongly Connected Components for directed graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-strongly-connected-components.html)) 13 | * Minimum Spanning Tree for weighted graph (Kruskal, Prim Lazy, Prim Eager) (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-kruskal.html)) 14 | * Shortest Paths (Dijkstra, Bellman-Ford, Topological Sort on DAG) (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-dijkstra.html)) 15 | * MaxFlow-MinCut (Ford-Fulkerson) (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-ford-fulkerson.html)) 16 | 17 | # Install 18 | 19 | ```bash 20 | npm install js-graph-algorithms 21 | ``` 22 | 23 | # Usage 24 | 25 | ### Create an undirected unweighted graph 26 | 27 | The sample code below shows how to create a undirected and unweighted graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-graph.html)): 28 | 29 | ```javascript 30 | var jsgraphs = require('js-graph-algorithms'); 31 | 32 | var g = new jsgraphs.Graph(6); // 6 is the number vertices in the graph 33 | g.addEdge(0, 5); // add undirected edge connecting vertex 0 to vertex 5 34 | g.addEdge(2, 4); 35 | g.addEdge(2, 3); 36 | g.addEdge(1, 2); 37 | g.addEdge(0, 1); 38 | g.addEdge(3, 4); 39 | g.addEdge(3, 5); 40 | g.addEdge(0, 2); 41 | 42 | g.node(2).label = 'Hello'; // assigned 'Hello' as label for node 2 43 | g.edge(0, 2).label = 'World'; // edge between 0 and 2 44 | 45 | console.log(g.V); // display 6, which is the number of vertices in g 46 | console.log(g.adj(0)); // display [5, 1, 2], which is the adjacent list to vertex 0 47 | ``` 48 | 49 | ### Create directed unweighted graph 50 | 51 | The sample code below shows how to create a direted and unweighted graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-digraph.html)): 52 | 53 | ```javascript 54 | var jsgraphs = require('js-graph-algorithms'); 55 | 56 | var g = new jsgraphs.DiGraph(13); // 13 is the number vertices in the graph 57 | g.addEdge(4, 2); // add directed edge from 4 to 2 58 | g.addEdge(2, 3); 59 | g.addEdge(3, 2); 60 | g.addEdge(6, 0); 61 | g.addEdge(0, 1); 62 | g.addEdge(2, 0); 63 | g.addEdge(11, 12); 64 | g.addEdge(12, 9); 65 | g.addEdge(9, 10); 66 | g.addEdge(9, 11); 67 | g.addEdge(7, 9); 68 | g.addEdge(10, 12); 69 | g.addEdge(11, 4); 70 | g.addEdge(4, 3); 71 | g.addEdge(3, 5); 72 | g.addEdge(6, 8); 73 | g.addEdge(8, 6); 74 | g.addEdge(5, 4); 75 | g.addEdge(0, 5); 76 | g.addEdge(6, 4); 77 | g.addEdge(6, 9); 78 | g.addEdge(7, 6); 79 | 80 | g.node(2).label = 'Hello'; // assign 'Hello' as label for node 2 81 | g.edge(0, 5).label = 'World'; // edge from 0 to 5 82 | 83 | console.log(g.V); // display 13, which is the number of vertices in g 84 | console.log(g.adj(0)); // display the adjacency list which are vertices directed from vertex 0 85 | ``` 86 | 87 | ### Create undirected weighted graph 88 | 89 | The sample code below shows show to create undirected weighted graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-weighted-graph.html)): 90 | 91 | 92 | ```javascript 93 | var jsgraphs = require('js-graph-algorithms'); 94 | var g = new jsgraphs.WeightedGraph(8); // 8 is the number vertices in the graph 95 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 96 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 97 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 98 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 99 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 100 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 101 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 102 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 103 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 104 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 105 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 106 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 107 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 108 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 109 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 110 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 111 | 112 | g.node(2).label = 'Hello'; // assign 'Hello' as label for node 2 113 | g.edge(4, 5).label = 'World'; // edge between node 4 and 5 114 | 115 | console.log(g.V); // display 13, which is the number of vertices in g 116 | console.log(g.adj(0)); // display the adjacency list which are undirected edges connected to vertex 0 117 | ``` 118 | 119 | ### Create directed weighted graph 120 | 121 | The sample code below shows show to create directed weighted graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-weighted-digraph.html)): 122 | 123 | ```javascript 124 | var jsgraphs = require('js-graph-algorithms'); 125 | var g = new jsgraphs.WeightedDiGraph(8); // 8 is the number vertices in the graph 126 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 127 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 128 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 129 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 130 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 131 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 132 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 133 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 134 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 135 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 136 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 137 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 138 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 139 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 140 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 141 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 142 | 143 | g.node(2).label = 'Hello'; 144 | g.edge(4, 5).label = 'World'; // edge from node 4 to node 5 145 | 146 | console.log(g.V); // display 13, which is the number of vertices in g 147 | console.log(g.adj(0)); // display the adjacency list which are directed edges from vertex 0 148 | ``` 149 | 150 | ### Depth First Search 151 | 152 | The sample code below show how to perform depth first search of an undirected graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-dfs.html)): 153 | 154 | ```javascript 155 | var jsgraphs = require('js-graph-algorithms'); 156 | 157 | var g = new jsgraphs.Graph(6); 158 | g.addEdge(0, 5); 159 | g.addEdge(2, 4); 160 | g.addEdge(2, 3); 161 | g.addEdge(1, 2); 162 | g.addEdge(0, 1); 163 | g.addEdge(3, 4); 164 | g.addEdge(3, 5); 165 | g.addEdge(0, 2); 166 | var s = 0; 167 | var dfs = new jsgraphs.DepthFirstSearch(g, s); 168 | 169 | 170 | for(var v=0; v < g.V; ++v) { 171 | if(dfs.hasPathTo(v)) { 172 | console.log(s + " is connected to " + v); 173 | console.log("path: " + dfs.pathTo(v)); 174 | } else { 175 | console.log('No path from ' + s + ' to ' + v); 176 | } 177 | } 178 | ``` 179 | 180 | ### Connected Components 181 | 182 | The sample code below show how to obtain the number of connected components in an undirected graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-connected-components.html)): 183 | 184 | ```javascript 185 | var jsgraphs = require('js-graph-algorithms'); 186 | 187 | var g = new jsgraphs.Graph(13); 188 | g.addEdge(0, 5); 189 | g.addEdge(4, 3); 190 | g.addEdge(0, 1); 191 | g.addEdge(9, 12); 192 | g.addEdge(6, 4); 193 | g.addEdge(5, 4); 194 | g.addEdge(0, 2); 195 | g.addEdge(11, 12); 196 | g.addEdge(9,10); 197 | g.addEdge(0, 6); 198 | g.addEdge(7, 8); 199 | g.addEdge(9, 11); 200 | g.addEdge(5, 3); 201 | 202 | var cc = new jsgraphs.ConnectedComponents(g); 203 | console.log(cc.componentCount()); // display 3 204 | for (var v = 0; v < g.V; ++v) { 205 | console.log('id[' + v + ']: ' + cc.componentId(v)); 206 | } 207 | ``` 208 | 209 | ### Topological Sort 210 | 211 | The sample code below show how to obtain the reverse post order of a topological sort in a directed acyclic graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-topo-sort.html)): 212 | 213 | ```javascript 214 | var jsgraphs = require('js-graph-algorithms'); 215 | 216 | var dag = new jsgraphs.DiGraph(7); // must be directed acyclic graph 217 | 218 | dag.addEdge(0, 5); 219 | dag.addEdge(0, 2); 220 | dag.addEdge(0, 1); 221 | dag.addEdge(3, 6); 222 | dag.addEdge(3, 5); 223 | dag.addEdge(3, 4); 224 | dag.addEdge(5, 4); 225 | dag.addEdge(6, 4); 226 | dag.addEdge(6, 0); 227 | dag.addEdge(3, 2); 228 | dag.addEdge(1, 4); 229 | 230 | var ts = new jsgraphs.TopologicalSort(dag); 231 | 232 | var order = ts.order(); 233 | console.log(order); // display array which is the topological sort order 234 | 235 | ``` 236 | 237 | ### Strongly Connected Components for Directed Graph 238 | 239 | The sample code below show how to obtain the strongly connected components from a directed graph (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-strongly-connected-components.html)): 240 | 241 | ```javascript 242 | var jsgraphs = require('js-graph-algorithms'); 243 | 244 | var graph = new jsgraphs.DiGraph(13); 245 | graph.addEdge(4, 2); 246 | graph.addEdge(2, 3); 247 | graph.addEdge(3, 2); 248 | graph.addEdge(6, 0); 249 | graph.addEdge(0, 1); 250 | graph.addEdge(2, 0); 251 | graph.addEdge(11, 12); 252 | graph.addEdge(12, 9); 253 | graph.addEdge(9, 10); 254 | graph.addEdge(9, 11); 255 | graph.addEdge(8, 9); 256 | graph.addEdge(10, 12); 257 | graph.addEdge(11, 4); 258 | graph.addEdge(4, 3); 259 | graph.addEdge(3, 5); 260 | graph.addEdge(7, 8); 261 | graph.addEdge(8, 7); 262 | graph.addEdge(5, 4); 263 | graph.addEdge(0, 5); 264 | graph.addEdge(6, 4); 265 | graph.addEdge(6, 9); 266 | graph.addEdge(7, 6); 267 | var scc = new jsgraphs.StronglyConnectedComponents(graph); 268 | console.log(scc.componentCount()); // display 5 269 | for (var v = 0; v < graph.V; ++v) { 270 | console.log('id[' + v + ']: ' + scc.componentId(v)); 271 | } 272 | ``` 273 | 274 | ### Use Kruskal algorithm to find the minimum spanning tree of a weighted graph 275 | 276 | The sample code below show how to obtain the minimum spanning tree from a weighted graph using Kruskal algorithm (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-kruskal.html)): 277 | 278 | ```javascript 279 | var jsgraphs = require('js-graph-algorithms'); 280 | var g = new jsgraphs.WeightedGraph(8); 281 | 282 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 283 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 284 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 285 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 286 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 287 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 288 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 289 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 290 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 291 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 292 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 293 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 294 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 295 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 296 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 297 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 298 | 299 | var kruskal = new jsgraphs.KruskalMST(g); 300 | var mst = kruskal.mst; 301 | for(var i=0; i < mst.length; ++i) { 302 | var e = mst[i]; 303 | var v = e.either(); 304 | var w = e.other(v); 305 | console.log('(' + v + ', ' + w + '): ' + e.weight); 306 | } 307 | ``` 308 | 309 | ### Use Lazy Prim algorithm to find the minimum spanning tree of a weighted graph 310 | 311 | The sample code below show how to obtain the minimum spanning tree from a weighted graph using Lazy Prim algorithm (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-lazy-prim.html)): 312 | 313 | ```javascript 314 | var jsgraphs = require('js-graph-algorithms'); 315 | var g = new jsgraphs.WeightedGraph(8); 316 | 317 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 318 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 319 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 320 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 321 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 322 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 323 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 324 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 325 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 326 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 327 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 328 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 329 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 330 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 331 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 332 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 333 | 334 | var prim = new jsgraphs.LazyPrimMST(g); 335 | var mst = prim.mst; 336 | for(var i=0; i < mst.length; ++i) { 337 | var e = mst[i]; 338 | var v = e.either(); 339 | var w = e.other(v); 340 | console.log('(' + v + ', ' + w + '): ' + e.weight); 341 | } 342 | ``` 343 | 344 | ### Use Eager Prim algorithm to find the minimum spanning tree of a weighted graph 345 | 346 | The sample code below show how to obtain the minimum spanning tree from a weighted graph using Eager Prim algorithm (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-eager-prim.html)): 347 | 348 | ```javascript 349 | var jsgraphs = require('js-graph-algorithms'); 350 | var g = new jsgraphs.WeightedGraph(8); 351 | 352 | g.addEdge(new jsgraphs.Edge(0, 7, 0.16)); 353 | g.addEdge(new jsgraphs.Edge(2, 3, 0.17)); 354 | g.addEdge(new jsgraphs.Edge(1, 7, 0.19)); 355 | g.addEdge(new jsgraphs.Edge(0, 2, 0.26)); 356 | g.addEdge(new jsgraphs.Edge(5, 7, 0.28)); 357 | g.addEdge(new jsgraphs.Edge(1, 3, 0.29)); 358 | g.addEdge(new jsgraphs.Edge(1, 5, 0.32)); 359 | g.addEdge(new jsgraphs.Edge(2, 7, 0.34)); 360 | g.addEdge(new jsgraphs.Edge(4, 5, 0.35)); 361 | g.addEdge(new jsgraphs.Edge(1, 2, 0.36)); 362 | g.addEdge(new jsgraphs.Edge(4, 7, 0.37)); 363 | g.addEdge(new jsgraphs.Edge(0, 4, 0.38)); 364 | g.addEdge(new jsgraphs.Edge(6, 2, 0.4)); 365 | g.addEdge(new jsgraphs.Edge(3, 6, 0.52)); 366 | g.addEdge(new jsgraphs.Edge(6, 0, 0.58)); 367 | g.addEdge(new jsgraphs.Edge(6, 4, 0.93)); 368 | 369 | var prim = new jsgraphs.EagerPrimMST(g); 370 | var mst = prim.mst; 371 | for(var i=0; i < mst.length; ++i) { 372 | var e = mst[i]; 373 | var v = e.either(); 374 | var w = e.other(v); 375 | console.log('(' + v + ', ' + w + '): ' + e.weight); 376 | } 377 | ``` 378 | 379 | ### Find the shortest paths using Dijkstra 380 | 381 | The sample code below show how to obtain the shortest paths from a starting point 0 on a weighted directed graph using Dijkstra (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-dijkstra.html)): 382 | 383 | ```javascript 384 | var jsgraphs = require('js-graph-algorithms'); 385 | var g = new jsgraphs.WeightedDiGraph(8); 386 | g.addEdge(new jsgraphs.Edge(0, 1, 5.0)); 387 | g.addEdge(new jsgraphs.Edge(0, 4, 9.0)); 388 | g.addEdge(new jsgraphs.Edge(0, 7, 8.0)); 389 | g.addEdge(new jsgraphs.Edge(1, 2, 12.0)); 390 | g.addEdge(new jsgraphs.Edge(1, 3, 15.0)); 391 | g.addEdge(new jsgraphs.Edge(1, 7, 4.0)); 392 | g.addEdge(new jsgraphs.Edge(2, 3, 3.0)); 393 | g.addEdge(new jsgraphs.Edge(2, 6, 11.0)); 394 | g.addEdge(new jsgraphs.Edge(3, 6, 9.0)); 395 | g.addEdge(new jsgraphs.Edge(4, 5, 5.0)); 396 | g.addEdge(new jsgraphs.Edge(4, 6, 20.0)); 397 | g.addEdge(new jsgraphs.Edge(4, 7, 5.0)); 398 | g.addEdge(new jsgraphs.Edge(5, 2, 1.0)); 399 | g.addEdge(new jsgraphs.Edge(5, 6, 13.0)); 400 | g.addEdge(new jsgraphs.Edge(7, 5, 6.0)); 401 | g.addEdge(new jsgraphs.Edge(7, 2, 7.0)); 402 | 403 | 404 | var dijkstra = new jsgraphs.Dijkstra(g, 0); 405 | 406 | for(var v = 1; v < g.V; ++v){ 407 | if(dijkstra.hasPathTo(v)){ 408 | var path = dijkstra.pathTo(v); 409 | console.log('=====path from 0 to ' + v + ' start=========='); 410 | for(var i = 0; i < path.length; ++i) { 411 | var e = path[i]; 412 | console.log(e.from() + ' => ' + e.to() + ': ' + e.weight); 413 | } 414 | console.log('=====path from 0 to ' + v + ' end=========='); 415 | console.log('=====distance: ' + dijkstra.distanceTo(v) + '========='); 416 | } 417 | } 418 | ``` 419 | 420 | ### Find the shortest paths using Bellman-Ford 421 | 422 | The sample code below show how to obtain the shortest paths from a starting point 0 on a weighted directed graph using Bellman-Ford: 423 | 424 | ```javascript 425 | var jsgraphs = require('js-graph-algorithms'); 426 | var g = new jsgraphs.WeightedDiGraph(8); 427 | g.addEdge(new jsgraphs.Edge(0, 1, 5.0)); 428 | g.addEdge(new jsgraphs.Edge(0, 4, 9.0)); 429 | g.addEdge(new jsgraphs.Edge(0, 7, 8.0)); 430 | g.addEdge(new jsgraphs.Edge(1, 2, 12.0)); 431 | g.addEdge(new jsgraphs.Edge(1, 3, 15.0)); 432 | g.addEdge(new jsgraphs.Edge(1, 7, 4.0)); 433 | g.addEdge(new jsgraphs.Edge(2, 3, 3.0)); 434 | g.addEdge(new jsgraphs.Edge(2, 6, 11.0)); 435 | g.addEdge(new jsgraphs.Edge(3, 6, 9.0)); 436 | g.addEdge(new jsgraphs.Edge(4, 5, 5.0)); 437 | g.addEdge(new jsgraphs.Edge(4, 6, 20.0)); 438 | g.addEdge(new jsgraphs.Edge(4, 7, 5.0)); 439 | g.addEdge(new jsgraphs.Edge(5, 2, 1.0)); 440 | g.addEdge(new jsgraphs.Edge(5, 6, 13.0)); 441 | g.addEdge(new jsgraphs.Edge(7, 5, 6.0)); 442 | g.addEdge(new jsgraphs.Edge(7, 2, 7.0)); 443 | 444 | 445 | var bf = new jsgraphs.BellmanFord(g, 0); 446 | 447 | for(var v = 1; v < g.V; ++v){ 448 | if(bf.hasPathTo(v)){ 449 | var path = bf.pathTo(v); 450 | console.log('=====path from 0 to ' + v + ' start=========='); 451 | for(var i = 0; i < path.length; ++i) { 452 | var e = path[i]; 453 | console.log(e.from() + ' => ' + e.to() + ': ' + e.weight); 454 | } 455 | console.log('=====path from 0 to ' + v + ' end=========='); 456 | console.log('=====distance: ' + bf.distanceTo(v) + '========='); 457 | } 458 | } 459 | ``` 460 | 461 | ### Find the shortest paths using Topological Sort Shortest Paths 462 | 463 | 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: 464 | 465 | ```javascript 466 | var jsgraphs = require('js-graph-algorithms'); 467 | var g = new jsgraphs.WeightedDiGraph(8); 468 | g.addEdge(new jsgraphs.Edge(0, 1, 5.0)); 469 | g.addEdge(new jsgraphs.Edge(0, 4, 9.0)); 470 | g.addEdge(new jsgraphs.Edge(0, 7, 8.0)); 471 | g.addEdge(new jsgraphs.Edge(1, 2, 12.0)); 472 | g.addEdge(new jsgraphs.Edge(1, 3, 15.0)); 473 | g.addEdge(new jsgraphs.Edge(1, 7, 4.0)); 474 | g.addEdge(new jsgraphs.Edge(2, 3, 3.0)); 475 | g.addEdge(new jsgraphs.Edge(2, 6, 11.0)); 476 | g.addEdge(new jsgraphs.Edge(3, 6, 9.0)); 477 | g.addEdge(new jsgraphs.Edge(4, 5, 5.0)); 478 | g.addEdge(new jsgraphs.Edge(4, 6, 20.0)); 479 | g.addEdge(new jsgraphs.Edge(4, 7, 5.0)); 480 | g.addEdge(new jsgraphs.Edge(5, 2, 1.0)); 481 | g.addEdge(new jsgraphs.Edge(5, 6, 13.0)); 482 | g.addEdge(new jsgraphs.Edge(7, 5, 6.0)); 483 | g.addEdge(new jsgraphs.Edge(7, 2, 7.0)); 484 | 485 | 486 | var bf = new jsgraphs.TopologicalSortShortestPaths(g, 0); 487 | 488 | for(var v = 1; v < g.V; ++v){ 489 | if(bf.hasPathTo(v)){ 490 | var path = bf.pathTo(v); 491 | console.log('=====path from 0 to ' + v + ' start=========='); 492 | for(var i = 0; i < path.length; ++i) { 493 | var e = path[i]; 494 | console.log(e.from() + ' => ' + e.to() + ': ' + e.weight); 495 | } 496 | console.log('=====path from 0 to ' + v + ' end=========='); 497 | console.log('=====distance: ' + bf.distanceTo(v) + '========='); 498 | } 499 | } 500 | ``` 501 | 502 | ### Find the MaxFlow-MinCut using Ford-Fulkerson algorithm 503 | 504 | The sample code below show how to obtain the MaxFlow-MinCut of a directed weighted graph using ford-fulkerson algorithm (Link: [HTML DEMO](https://rawgit.com/chen0040/js-graph-algorithms/master/examples/example-ford-fulkerson.html)): 505 | 506 | ```javascript 507 | var jsgraphs = require('js-graph-algorithms'); 508 | var g = new jsgraphs.FlowNetwork(8); 509 | g.addEdge(new jsgraphs.FlowEdge(0, 1, 10)); 510 | g.addEdge(new jsgraphs.FlowEdge(0, 2, 5)); 511 | g.addEdge(new jsgraphs.FlowEdge(0, 3, 15)); 512 | g.addEdge(new jsgraphs.FlowEdge(1, 4, 9)); 513 | g.addEdge(new jsgraphs.FlowEdge(1, 5, 15)); 514 | g.addEdge(new jsgraphs.FlowEdge(1, 2, 4)); 515 | g.addEdge(new jsgraphs.FlowEdge(2, 5, 8)); 516 | g.addEdge(new jsgraphs.FlowEdge(2, 3, 4)); 517 | g.addEdge(new jsgraphs.FlowEdge(3, 6, 16)); 518 | g.addEdge(new jsgraphs.FlowEdge(4, 5, 15)); 519 | g.addEdge(new jsgraphs.FlowEdge(4, 7, 10)); 520 | g.addEdge(new jsgraphs.FlowEdge(5, 7, 10)); 521 | g.addEdge(new jsgraphs.FlowEdge(5, 6, 15)); 522 | g.addEdge(new jsgraphs.FlowEdge(6, 2, 6)); 523 | g.addEdge(new jsgraphs.FlowEdge(6, 7, 10)); 524 | 525 | g.node(2).label = 'Hello'; 526 | g.edge(0, 1).label = 'World'; 527 | 528 | var source = 0; 529 | var target = 7; 530 | var ff = new jsgraphs.FordFulkerson(g, source, target); 531 | console.log('max-flow: ' + ff.value); 532 | 533 | var minCut = ff.minCut(g); 534 | 535 | for(var i = 0; i < minCut.length; ++i) { 536 | var e = minCut[i]; 537 | console.log('min-cut: (' + e.from() + ", " + e.to() + ')'); 538 | } 539 | ``` -------------------------------------------------------------------------------- /third-party-libs/vis/vis.min.css: -------------------------------------------------------------------------------- 1 | .vis .overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-active{box-shadow:0 0 10px #86d5f8}.vis [class*=span]{min-height:0;width:auto}div.vis-configuration{position:relative;display:block;float:left;font-size:12px}div.vis-configuration-wrapper{display:block;width:700px}div.vis-configuration-wrapper::after{clear:both;content:"";display:block}div.vis-configuration.vis-config-option-container{display:block;width:495px;background-color:#fff;border:2px solid #f7f8fa;border-radius:4px;margin-top:20px;left:10px;padding-left:5px}div.vis-configuration.vis-config-button{display:block;width:495px;height:25px;vertical-align:middle;line-height:25px;background-color:#f7f8fa;border:2px solid #ceced0;border-radius:4px;margin-top:20px;left:10px;padding-left:5px;cursor:pointer;margin-bottom:30px}div.vis-configuration.vis-config-button.hover{background-color:#4588e6;border:2px solid #214373;color:#fff}div.vis-configuration.vis-config-item{display:block;float:left;width:495px;height:25px;vertical-align:middle;line-height:25px}div.vis-configuration.vis-config-item.vis-config-s2{left:10px;background-color:#f7f8fa;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s3{left:20px;background-color:#e4e9f0;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-item.vis-config-s4{left:30px;background-color:#cfd8e6;padding-left:5px;border-radius:3px}div.vis-configuration.vis-config-header{font-size:18px;font-weight:700}div.vis-configuration.vis-config-label{width:120px;height:25px;line-height:25px}div.vis-configuration.vis-config-label.vis-config-s3{width:110px}div.vis-configuration.vis-config-label.vis-config-s4{width:100px}div.vis-configuration.vis-config-colorBlock{top:1px;width:30px;height:19px;border:1px solid #444;border-radius:2px;padding:0;margin:0;cursor:pointer}input.vis-configuration.vis-config-checkbox{left:-5px}input.vis-configuration.vis-config-rangeinput{position:relative;top:-5px;width:60px;padding:1px;margin:0;pointer-events:none}input.vis-configuration.vis-config-range{-webkit-appearance:none;border:0 solid #fff;background-color:rgba(0,0,0,0);width:300px;height:20px}input.vis-configuration.vis-config-range::-webkit-slider-runnable-track{width:300px;height:5px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-webkit-slider-thumb{-webkit-appearance:none;border:1px solid #14334b;height:17px;width:17px;border-radius:50%;background:#3876c2;background:-moz-linear-gradient(top,#3876c2 0,#385380 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3876c2),color-stop(100%,#385380));background:-webkit-linear-gradient(top,#3876c2 0,#385380 100%);background:-o-linear-gradient(top,#3876c2 0,#385380 100%);background:-ms-linear-gradient(top,#3876c2 0,#385380 100%);background:linear-gradient(to bottom,#3876c2 0,#385380 100%);box-shadow:#111927 0 0 1px 0;margin-top:-7px}input.vis-configuration.vis-config-range:focus{outline:0}input.vis-configuration.vis-config-range:focus::-webkit-slider-runnable-track{background:#9d9d9d;background:-moz-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#9d9d9d),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-o-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#9d9d9d 0,#c8c8c8 99%);background:linear-gradient(to bottom,#9d9d9d 0,#c8c8c8 99%)}input.vis-configuration.vis-config-range::-moz-range-track{width:300px;height:10px;background:#dedede;background:-moz-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#dedede),color-stop(99%,#c8c8c8));background:-webkit-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-o-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:-ms-linear-gradient(top,#dedede 0,#c8c8c8 99%);background:linear-gradient(to bottom,#dedede 0,#c8c8c8 99%);border:1px solid #999;box-shadow:#aaa 0 0 3px 0;border-radius:3px}input.vis-configuration.vis-config-range::-moz-range-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}input.vis-configuration.vis-config-range::-ms-track{width:300px;height:5px;background:0 0;border-color:transparent;border-width:6px 0;color:transparent}input.vis-configuration.vis-config-range::-ms-fill-lower{background:#777;border-radius:10px}input.vis-configuration.vis-config-range::-ms-fill-upper{background:#ddd;border-radius:10px}input.vis-configuration.vis-config-range::-ms-thumb{border:none;height:16px;width:16px;border-radius:50%;background:#385380}input.vis-configuration.vis-config-range:focus::-ms-fill-lower{background:#888}input.vis-configuration.vis-config-range:focus::-ms-fill-upper{background:#ccc}.vis-configuration-popup{position:absolute;background:rgba(57,76,89,.85);border:2px solid #f2faff;line-height:30px;height:30px;width:150px;text-align:center;color:#fff;font-size:14px;border-radius:4px;-webkit-transition:opacity .3s ease-in-out;-moz-transition:opacity .3s ease-in-out;transition:opacity .3s ease-in-out}.vis-configuration-popup:after,.vis-configuration-popup:before{left:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.vis-configuration-popup:after{border-color:rgba(136,183,213,0);border-left-color:rgba(57,76,89,.85);border-width:8px;margin-top:-8px}.vis-configuration-popup:before{border-color:rgba(194,225,245,0);border-left-color:#f2faff;border-width:12px;margin-top:-12px}div.vis-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;font-family:verdana;font-size:14px;color:#000;background-color:#f5f4ed;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid #808074;box-shadow:3px 3px 10px rgba(0,0,0,.2);pointer-events:none;z-index:5}div.vis-color-picker{position:absolute;top:0;left:30px;margin-top:-140px;margin-left:30px;width:310px;height:444px;z-index:1;padding:10px;border-radius:15px;background-color:#fff;display:none;box-shadow:rgba(0,0,0,.5) 0 0 10px 0}div.vis-color-picker div.vis-arrow{position:absolute;top:147px;left:5px}div.vis-color-picker div.vis-arrow::after,div.vis-color-picker div.vis-arrow::before{right:100%;top:50%;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}div.vis-color-picker div.vis-arrow:after{border-color:rgba(255,255,255,0);border-right-color:#fff;border-width:30px;margin-top:-30px}div.vis-color-picker div.vis-color{position:absolute;width:289px;height:289px;cursor:pointer}div.vis-color-picker div.vis-brightness{position:absolute;top:313px}div.vis-color-picker div.vis-opacity{position:absolute;top:350px}div.vis-color-picker div.vis-selector{position:absolute;top:137px;left:137px;width:15px;height:15px;border-radius:15px;border:1px solid #fff;background:#4c4c4c;background:-moz-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4c4c4c),color-stop(12%,#595959),color-stop(25%,#666),color-stop(39%,#474747),color-stop(50%,#2c2c2c),color-stop(51%,#000),color-stop(60%,#111),color-stop(76%,#2b2b2b),color-stop(91%,#1c1c1c),color-stop(100%,#131313));background:-webkit-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-o-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:-ms-linear-gradient(top,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%);background:linear-gradient(to bottom,#4c4c4c 0,#595959 12%,#666 25%,#474747 39%,#2c2c2c 50%,#000 51%,#111 60%,#2b2b2b 76%,#1c1c1c 91%,#131313 100%)}div.vis-color-picker div.vis-new-color{position:absolute;width:140px;height:20px;border:1px solid rgba(0,0,0,.1);border-radius:5px;top:380px;left:159px;text-align:right;padding-right:2px;font-size:10px;color:rgba(0,0,0,.4);vertical-align:middle;line-height:20px}div.vis-color-picker div.vis-initial-color{position:absolute;width:140px;height:20px;border:1px solid rgba(0,0,0,.1);border-radius:5px;top:380px;left:10px;text-align:left;padding-left:2px;font-size:10px;color:rgba(0,0,0,.4);vertical-align:middle;line-height:20px}div.vis-color-picker div.vis-label{position:absolute;width:300px;left:10px}div.vis-color-picker div.vis-label.vis-brightness{top:300px}div.vis-color-picker div.vis-label.vis-opacity{top:338px}div.vis-color-picker div.vis-button{position:absolute;width:68px;height:25px;border-radius:10px;vertical-align:middle;text-align:center;line-height:25px;top:410px;border:2px solid #d9d9d9;background-color:#f7f7f7;cursor:pointer}div.vis-color-picker div.vis-button.vis-cancel{left:5px}div.vis-color-picker div.vis-button.vis-load{left:82px}div.vis-color-picker div.vis-button.vis-apply{left:159px}div.vis-color-picker div.vis-button.vis-save{left:236px}div.vis-color-picker input.vis-range{width:290px;height:20px}div.vis-network div.vis-manipulation{box-sizing:content-box;border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);padding-top:4px;position:absolute;left:0;top:0;width:100%;height:28px}div.vis-network div.vis-edit-mode{position:absolute;left:0;top:5px;height:30px}div.vis-network div.vis-close{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-repeat:no-repeat;background-image:url(img/network/cross.png);cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-close:hover{opacity:.6}div.vis-network div.vis-edit-mode div.vis-button,div.vis-network div.vis-manipulation div.vis-button{float:left;font-family:verdana;font-size:12px;-moz-border-radius:15px;border-radius:15px;display:inline-block;background-position:0 0;background-repeat:no-repeat;height:24px;margin-left:10px;cursor:pointer;padding:0 8px 0 8px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-manipulation div.vis-button:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.vis-network div.vis-manipulation div.vis-button:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.vis-network div.vis-manipulation div.vis-button.vis-back{background-image:url(img/network/backIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.vis-network div.vis-manipulation div.vis-button.vis-none:active{box-shadow:1px 1px 8px transparent}div.vis-network div.vis-manipulation div.vis-button.vis-none{padding:0}div.vis-network div.vis-manipulation div.notification{margin:2px;font-weight:700}div.vis-network div.vis-manipulation div.vis-button.vis-add{background-image:url(img/network/addNodeIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit,div.vis-network div.vis-manipulation div.vis-button.vis-edit{background-image:url(img/network/editIcon.png)}div.vis-network div.vis-edit-mode div.vis-button.vis-edit.vis-edit-mode{background-color:#fcfcfc;border:1px solid #ccc}div.vis-network div.vis-manipulation div.vis-button.vis-connect{background-image:url(img/network/connectIcon.png)}div.vis-network div.vis-manipulation div.vis-button.vis-delete{background-image:url(img/network/deleteIcon.png)}div.vis-network div.vis-edit-mode div.vis-label,div.vis-network div.vis-manipulation div.vis-label{margin:0 0 0 23px;line-height:25px}div.vis-network div.vis-manipulation div.vis-separator-line{float:left;display:inline-block;width:1px;height:21px;background-color:#bdbdbd;margin:0 7px 0 15px}div.vis-network div.vis-navigation div.vis-button{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;display:inline-block;background-position:2px 2px;background-repeat:no-repeat;cursor:pointer;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div.vis-network div.vis-navigation div.vis-button:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.vis-network div.vis-navigation div.vis-button:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.vis-network div.vis-navigation div.vis-button.vis-up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.vis-network div.vis-navigation div.vis-button.vis-left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.vis-network div.vis-navigation div.vis-button.vis-right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.vis-network div.vis-navigation div.vis-button.vis-zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.vis-network div.vis-navigation div.vis-button.vis-zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.vis-network div.vis-navigation div.vis-button.vis-zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px}.vis-current-time{background-color:#ff7f6e;width:2px;z-index:1;pointer-events:none}.vis-rolling-mode-btn{height:40px;width:40px;position:absolute;top:7px;right:20px;border-radius:50%;font-size:28px;cursor:pointer;opacity:.8;color:#fff;font-weight:700;text-align:center;background:#3876c2}.vis-rolling-mode-btn:before{content:"\26F6"}.vis-rolling-mode-btn:hover{opacity:1}.vis-custom-time{background-color:#6e94ff;width:2px;cursor:move;z-index:1}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-minor{border-color:#e5e5e5}.vis-panel.vis-background.vis-horizontal .vis-grid.vis-major{border-color:#bfbfbf}.vis-data-axis .vis-y-axis.vis-major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-major.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis-data-axis .vis-y-axis.vis-minor.vis-measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis-data-axis .vis-y-axis.vis-title.vis-measure{padding:0;margin:0;visibility:hidden;width:auto}.vis-data-axis .vis-y-axis.vis-title.vis-left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis-data-axis .vis-y-axis.vis-title.vis-right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis-legend{background-color:rgba(247,252,255,.65);padding:5px;border:1px solid #b3b3b3;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis-legend-text{white-space:nowrap;display:inline-block}.vis-item{position:absolute;color:#1a1a1a;border-color:#97b0f8;border-width:1px;background-color:#d5ddf6;display:inline-block;z-index:1}.vis-item.vis-selected{border-color:#ffc200;background-color:#fff785;z-index:2}.vis-editable.vis-selected{cursor:move}.vis-item.vis-point.vis-selected{background-color:#fff785}.vis-item.vis-box{text-align:center;border-style:solid;border-radius:2px}.vis-item.vis-point{background:0 0}.vis-item.vis-dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis-item.vis-range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis-item.vis-background{border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis-item .vis-item-overflow{position:relative;width:100%;height:100%;padding:0;margin:0;overflow:hidden}.vis-item-visible-frame{white-space:nowrap}.vis-item.vis-range .vis-item-content{position:relative;display:inline-block}.vis-item.vis-background .vis-item-content{position:absolute;display:inline-block}.vis-item.vis-line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis-item .vis-item-content{white-space:nowrap;box-sizing:border-box;padding:5px}.vis-item .vis-onUpdateTime-tooltip{position:absolute;background:#4f81bd;color:#fff;width:200px;text-align:center;white-space:nowrap;padding:5px;border-radius:1px;transition:.4s;-o-transition:.4s;-moz-transition:.4s;-webkit-transition:.4s}.vis-item .vis-delete,.vis-item .vis-delete-rtl{position:absolute;top:0;width:24px;height:24px;box-sizing:border-box;padding:0 5px;cursor:pointer;-webkit-transition:background .2s linear;-moz-transition:background .2s linear;-ms-transition:background .2s linear;-o-transition:background .2s linear;transition:background .2s linear}.vis-item .vis-delete{right:-24px}.vis-item .vis-delete-rtl{left:-24px}.vis-item .vis-delete-rtl:after,.vis-item .vis-delete:after{content:"\00D7";color:red;font-family:arial,sans-serif;font-size:22px;font-weight:700;-webkit-transition:color .2s linear;-moz-transition:color .2s linear;-ms-transition:color .2s linear;-o-transition:color .2s linear;transition:color .2s linear}.vis-item .vis-delete-rtl:hover,.vis-item .vis-delete:hover{background:red}.vis-item .vis-delete-rtl:hover:after,.vis-item .vis-delete:hover:after{color:#fff}.vis-item .vis-drag-center{position:absolute;width:100%;height:100%;top:0;left:0;cursor:move}.vis-item.vis-range .vis-drag-left{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;left:-4px;cursor:w-resize}.vis-item.vis-range .vis-drag-right{position:absolute;width:24px;max-width:20%;min-width:2px;height:100%;top:0;right:-4px;cursor:e-resize}.vis-range.vis-item.vis-readonly .vis-drag-left,.vis-range.vis-item.vis-readonly .vis-drag-right{cursor:auto}.vis-itemset{position:relative;padding:0;margin:0;box-sizing:border-box}.vis-itemset .vis-background,.vis-itemset .vis-foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis-axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis-foreground .vis-group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis-foreground .vis-group:last-child{border-bottom:none}.vis-nesting-group{cursor:pointer}.vis-nested-group{background:#f5f5f5}.vis-label.vis-nesting-group.expanded:before{content:"\25BC"}.vis-label.vis-nesting-group.collapsed-rtl:before{content:"\25C0"}.vis-label.vis-nesting-group.collapsed:before{content:"\25B6"}.vis-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.vis-labelset{position:relative;overflow:hidden;box-sizing:border-box}.vis-labelset .vis-label{position:relative;left:0;top:0;width:100%;color:#4d4d4d;box-sizing:border-box}.vis-labelset .vis-label{border-bottom:1px solid #bfbfbf}.vis-labelset .vis-label.draggable{cursor:pointer}.vis-labelset .vis-label:last-child{border-bottom:none}.vis-labelset .vis-label .vis-inner{display:inline-block;padding:5px}.vis-labelset .vis-label .vis-inner.vis-hidden{padding:0}.vis-panel{position:absolute;padding:0;margin:0;box-sizing:border-box}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right,.vis-panel.vis-top{border:1px #bfbfbf}.vis-panel.vis-center,.vis-panel.vis-left,.vis-panel.vis-right{border-top-style:solid;border-bottom-style:solid;overflow:hidden}.vis-left.vis-panel.vis-vertical-scroll,.vis-right.vis-panel.vis-vertical-scroll{height:100%;overflow-x:hidden;overflow-y:scroll}.vis-left.vis-panel.vis-vertical-scroll{direction:rtl}.vis-left.vis-panel.vis-vertical-scroll .vis-content{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll{direction:ltr}.vis-right.vis-panel.vis-vertical-scroll .vis-content{direction:rtl}.vis-panel.vis-bottom,.vis-panel.vis-center,.vis-panel.vis-top{border-left-style:solid;border-right-style:solid}.vis-background{overflow:hidden}.vis-panel>.vis-content{position:relative}.vis-panel .vis-shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis-panel .vis-shadow.vis-top{top:-1px;left:0}.vis-panel .vis-shadow.vis-bottom{bottom:-1px;left:0}.vis-graph-group0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis-graph-group1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis-graph-group2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis-graph-group3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis-graph-group4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis-graph-group5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis-graph-group6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis-graph-group7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis-graph-group8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis-graph-group9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis-timeline .vis-fill{fill-opacity:.1;stroke:none}.vis-timeline .vis-bar{fill-opacity:.5;stroke-width:1px}.vis-timeline .vis-point{stroke-width:2px;fill-opacity:1}.vis-timeline .vis-legend-background{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis-timeline .vis-outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis-timeline .vis-icon-fill{fill-opacity:.3;stroke:none}.vis-time-axis{position:relative;overflow:hidden}.vis-time-axis.vis-foreground{top:0;left:0;width:100%}.vis-time-axis.vis-background{position:absolute;top:0;left:0;width:100%;height:100%}.vis-time-axis .vis-text{position:absolute;color:#4d4d4d;padding:3px;overflow:hidden;box-sizing:border-box;white-space:nowrap}.vis-time-axis .vis-text.vis-measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis-time-axis .vis-grid.vis-vertical{position:absolute;border-left:1px solid}.vis-time-axis .vis-grid.vis-vertical-rtl{position:absolute;border-right:1px solid}.vis-time-axis .vis-grid.vis-minor{border-color:#e5e5e5}.vis-time-axis .vis-grid.vis-major{border-color:#bfbfbf}.vis-timeline{position:relative;border:1px solid #bfbfbf;overflow:hidden;padding:0;margin:0;box-sizing:border-box} -------------------------------------------------------------------------------- /src/jsgraphs.js: -------------------------------------------------------------------------------- 1 | var jsgraphs = jsgraphs || {}; 2 | 3 | (function(jss){ 4 | 5 | jss.less = function(a1, a2, compare) { 6 | return compare(a1, a2) < 0; 7 | }; 8 | 9 | jss.exchange = function(a, i, j) { 10 | var temp = a[i]; 11 | a[i] = a[j]; 12 | a[j] = temp; 13 | }; 14 | 15 | var StackNode = function (value) { 16 | this.value = value; 17 | this.next = null; 18 | }; 19 | 20 | jss.StackNode = StackNode; 21 | 22 | var Stack = function() { 23 | this.N = 0; 24 | this.first = null; 25 | }; 26 | 27 | Stack.prototype.push = function (a) { 28 | this.first = this._push(this.first, a); 29 | }; 30 | 31 | Stack.prototype._push = function(x, a) { 32 | if(x == null) { 33 | this.N++; 34 | return new jss.StackNode(a); 35 | } 36 | var oldX = x; 37 | this.N++; 38 | x = new jss.StackNode(a); 39 | x.next = oldX; 40 | return x; 41 | }; 42 | 43 | Stack.prototype.pop = function () { 44 | if (this.first == null) { 45 | return undefined; 46 | } 47 | 48 | var oldFirst = this.first; 49 | var item = oldFirst.value; 50 | this.first = oldFirst.next; 51 | this.N--; 52 | 53 | return item; 54 | }; 55 | 56 | Stack.prototype.size = function() { 57 | return this.N; 58 | }; 59 | 60 | Stack.prototype.isEmpty = function() { 61 | return this.N == 0; 62 | }; 63 | 64 | Stack.prototype.peep = function() { 65 | if (this.first == null) { 66 | return undefined; 67 | } 68 | 69 | return this.first.value; 70 | }; 71 | 72 | Stack.prototype.toArray = function() { 73 | var result = []; 74 | x = this.first; 75 | while (x != null) { 76 | result.push(x.value); 77 | x = x.next; 78 | } 79 | return result; 80 | }; 81 | 82 | jss.Stack = Stack; 83 | 84 | var QueueNode = function(a) { 85 | this.value = a; 86 | this.next = null; 87 | }; 88 | 89 | jss.QueueNode = QueueNode; 90 | 91 | var Queue = function() { 92 | this.first = null; 93 | this.last = null; 94 | this.N = 0; 95 | }; 96 | 97 | Queue.prototype.enqueue = function(item) { 98 | var oldLast = this.last; 99 | this.last = new jss.QueueNode(item); 100 | if(oldLast != null){ 101 | oldLast.next = this.last; 102 | } 103 | if (this.first == null) { 104 | this.first = this.last; 105 | } 106 | this.N++; 107 | }; 108 | 109 | Queue.prototype.dequeue = function() { 110 | if(this.first == null) { 111 | return undefined; 112 | } 113 | 114 | var oldFirst = this.first; 115 | var item = oldFirst.value; 116 | this.first = oldFirst.next; 117 | 118 | if(this.first == null) { 119 | this.last = null; 120 | } 121 | 122 | this.N--; 123 | 124 | return item; 125 | }; 126 | 127 | Queue.prototype.size = function() { 128 | return this.N; 129 | }; 130 | 131 | Queue.prototype.isEmpty = function() { 132 | return this.N == 0; 133 | }; 134 | 135 | Queue.prototype.toArray = function() { 136 | var result = []; 137 | var x = this.first; 138 | while (x != null) { 139 | result.push(x.value); 140 | x = x.next; 141 | } 142 | return result; 143 | }; 144 | 145 | jss.Queue = Queue; 146 | 147 | var MinPQ = function(compare) { 148 | this.s = []; 149 | this.N = 0; 150 | if(!compare) { 151 | compare = function(a1, a2) { 152 | return a1 - a2; 153 | }; 154 | } 155 | this.compare = compare; 156 | }; 157 | 158 | MinPQ.prototype.enqueue = function(item) { 159 | while(this.s.lengh <= this.N+1) { 160 | this.s.push(0); 161 | } 162 | this.s[++this.N] = item; 163 | this.swim(this.N); 164 | }; 165 | 166 | MinPQ.prototype.swim = function(k) { 167 | while (k > 1){ 168 | var parent = Math.floor(k / 2); 169 | if(jss.less(this.s[k], this.s[parent], this.compare)){ 170 | jss.exchange(this.s, k, parent); 171 | k = parent; 172 | } else { 173 | break; 174 | } 175 | } 176 | }; 177 | 178 | MinPQ.prototype.delMin = function() { 179 | if(this.N == 0) { 180 | return undefined; 181 | } 182 | 183 | var item = this.s[1]; 184 | jss.exchange(this.s, 1, this.N--); 185 | this.sink(1); 186 | return item; 187 | }; 188 | 189 | MinPQ.prototype.sink = function(k) { 190 | while(k * 2 <= this.N) { 191 | var child = 2 * k; 192 | if(child < this.N && jss.less(this.s[child+1], this.s[child], this.compare)){ 193 | child++; 194 | } 195 | if(jss.less(this.s[child], this.s[k], this.compare)){ 196 | jss.exchange(this.s, child, k); 197 | k = child; 198 | } else { 199 | break; 200 | } 201 | } 202 | }; 203 | 204 | MinPQ.prototype.size = function(){ 205 | return this.N; 206 | }; 207 | 208 | MinPQ.prototype.isEmpty = function() { 209 | return this.N == 0; 210 | }; 211 | 212 | jss.MinPQ = MinPQ; 213 | 214 | var QuickUnion = function(V) { 215 | this.id = []; 216 | for (var v = 0; v < V; ++v) { 217 | this.id.push(v); 218 | } 219 | }; 220 | 221 | QuickUnion.prototype.union = function(v, w) { 222 | var q = this.root(v); 223 | var p = this.root(w); 224 | 225 | if(p != q) { 226 | this.id[p] = q; 227 | } 228 | }; 229 | 230 | QuickUnion.prototype.root = function(q) { 231 | while(this.id[q] != q) { 232 | q = this.id[q]; 233 | } 234 | return q; 235 | }; 236 | 237 | QuickUnion.prototype.connected = function(v, w) { 238 | return this.root(v) == this.root(w); 239 | }; 240 | 241 | jss.QuickUnion = QuickUnion; 242 | 243 | var IndexMinPQ = function(N, compare) { 244 | this.keys = []; 245 | this.pq = []; 246 | this.qp = []; // positions of key in pq 247 | for(var i = 0; i <= N; ++i) { 248 | this.keys.push(null); 249 | this.pq.push(0); 250 | this.qp.push(-1); 251 | } 252 | this.N = 0; 253 | 254 | if(!compare) { 255 | compare = function(a1, a2) { 256 | return a1 - a2; 257 | }; 258 | } 259 | this.compare = compare; 260 | }; 261 | 262 | IndexMinPQ.prototype.insert = function (index, key) { 263 | this.keys[index] = key; 264 | 265 | this.pq[++this.N] = index; 266 | this.qp[index] = this.N; 267 | this.swim(this.N); 268 | }; 269 | 270 | IndexMinPQ.prototype.decreaseKey = function(index, key) { 271 | if(jss.less(key, this.keys[index], this.compare)){ 272 | this.keys[index] = key; 273 | this.swim(this.qp[index]); 274 | } 275 | }; 276 | 277 | IndexMinPQ.prototype.minKey = function() { 278 | return this.keys[this.pq[1]]; 279 | }; 280 | 281 | IndexMinPQ.prototype.min = function() { 282 | return this.pq[1]; 283 | }; 284 | 285 | IndexMinPQ.prototype.delMin = function() { 286 | var key = this.pq[1]; 287 | jss.exchange(this.pq, 1, this.N); 288 | this.qp[this.pq[1]] = 1; 289 | 290 | this.qp[this.pq[this.N]] = -1; 291 | this.keys[this.pq[this.N]] = null; 292 | 293 | this.N--; 294 | 295 | this.sink(1); 296 | 297 | return key; 298 | }; 299 | 300 | IndexMinPQ.prototype.swim = function (k) { 301 | while( k > 1) { 302 | var parent = Math.floor(k / 2); 303 | if(jss.less(this.keys[this.pq[k]], this.keys[this.pq[parent]], this.compare)){ 304 | jss.exchange(this.pq, k, parent); 305 | this.qp[this.pq[k]] = k; 306 | this.qp[this.pq[parent]] = parent; 307 | k = parent; 308 | } else { 309 | break; 310 | } 311 | } 312 | }; 313 | 314 | IndexMinPQ.prototype.sink = function (k) { 315 | while(2 * k <= this.N) { 316 | var child = k * 2; 317 | if(child < this.N && jss.less(this.keys[this.pq[child+1]], this.keys[this.pq[child]], this.compare)){ 318 | child++; 319 | } 320 | if(jss.less(this.keys[this.pq[child]], this.keys[this.pq[k]], this.compare)) { 321 | jss.exchange(this.pq, k, child); 322 | this.qp[this.pq[k]] = k; 323 | this.qp[this.pq[child]] = child; 324 | k = child; 325 | } else { 326 | break; 327 | } 328 | } 329 | }; 330 | 331 | IndexMinPQ.prototype.containsIndex = function (index) { 332 | return this.qp[index] != -1; 333 | }; 334 | 335 | IndexMinPQ.prototype.isEmpty = function() { 336 | return this.N == 0; 337 | }; 338 | 339 | IndexMinPQ.prototype.size = function() { 340 | return this.N; 341 | } 342 | 343 | jss.IndexMinPQ = IndexMinPQ; 344 | 345 | var Graph = function (V) { 346 | this.V = V; 347 | this.adjList = []; 348 | this.nodeInfo = []; 349 | this.edges = {}; 350 | for (var i = 0; i < V; ++i) { 351 | this.adjList.push([]); 352 | this.nodeInfo.push({}); 353 | } 354 | }; 355 | 356 | Graph.prototype.addEdge = function(v, w){ 357 | this.adjList[v].push(w); 358 | this.adjList[w].push(v); 359 | var edge_id = v + '_' + w; 360 | if(v > w) { 361 | edge_id = w + '_' + v; 362 | } 363 | this.edges[edge_id] = new jss.Edge(v, w, 0); 364 | }; 365 | 366 | Graph.prototype.adj = function(v) { 367 | return this.adjList[v]; 368 | }; 369 | 370 | Graph.prototype.node = function(v) { 371 | return this.nodeInfo[v]; 372 | }; 373 | 374 | Graph.prototype.edge = function(v, w) { 375 | var edge_id = v + '_' + w; 376 | if(v > w) { 377 | edge_id = w + '_' + v; 378 | } 379 | if (edge_id in this.edges) { 380 | return this.edges[edge_id]; 381 | } 382 | return null; 383 | }; 384 | 385 | jss.Graph = Graph; 386 | 387 | var DiGraph = function(V) { 388 | this.V = V; 389 | this.adjList = []; 390 | this.nodeInfo = []; 391 | this.edges = {}; 392 | for (var v = 0; v < V; ++v){ 393 | this.adjList.push([]); 394 | this.nodeInfo.push({}); 395 | } 396 | }; 397 | 398 | DiGraph.prototype.addEdge = function(v, w){ 399 | this.adjList[v].push(w); 400 | var edge_id = v + '_' + w; 401 | this.edges[edge_id] = new jss.Edge(v, w, 0); 402 | }; 403 | 404 | DiGraph.prototype.edge = function(v, w) { 405 | var edge_id = v + '_' + w; 406 | if(edge_id in this.edges) { 407 | return this.edges[edge_id]; 408 | } else { 409 | return null; 410 | } 411 | }; 412 | 413 | DiGraph.prototype.adj = function(v) { 414 | return this.adjList[v]; 415 | }; 416 | 417 | DiGraph.prototype.node = function(v) { 418 | return this.nodeInfo[v]; 419 | }; 420 | 421 | DiGraph.prototype.reverse = function(){ 422 | var g = new DiGraph(this.V); 423 | for (var v = 0; v < this.V; ++v) { 424 | var adj_v = this.adjList[v]; 425 | for (var i = 0; i < adj_v.length; ++i){ 426 | var w = adj_v[i]; 427 | g.addEdge(w, v); 428 | } 429 | } 430 | return g; 431 | }; 432 | 433 | jss.DiGraph = DiGraph; 434 | 435 | var Edge = function(v, w, weight) { 436 | this.v = v; 437 | this.w = w; 438 | this.weight = weight; 439 | }; 440 | 441 | Edge.prototype.either = function() { 442 | return this.v; 443 | }; 444 | 445 | Edge.prototype.other = function(x) { 446 | return x == this.v ? this.w : this.v; 447 | }; 448 | 449 | Edge.prototype.from = function() { 450 | return this.v; 451 | }; 452 | 453 | Edge.prototype.to = function() { 454 | return this.w; 455 | }; 456 | 457 | jss.Edge = Edge; 458 | 459 | var WeightedGraph = function(V) { 460 | this.V = V; 461 | this.adjList = []; 462 | this.nodeInfo = []; 463 | 464 | for ( var v = 0; v < V; ++v) { 465 | this.adjList.push([]); 466 | this.nodeInfo.push({}); 467 | } 468 | }; 469 | 470 | WeightedGraph.prototype.adj = function(v) { 471 | return this.adjList[v]; 472 | }; 473 | 474 | WeightedGraph.prototype.edge = function(v, w) { 475 | var adj_v = this.adjList[v]; 476 | for(var i=0; i < adj_v.length; ++i) { 477 | var x = adj_v[i].other(v); 478 | if(x == w) { 479 | return adj_v[i]; 480 | } 481 | } 482 | return null; 483 | }; 484 | 485 | WeightedGraph.prototype.node = function(v) { 486 | return this.nodeInfo[v]; 487 | }; 488 | 489 | WeightedGraph.prototype.addEdge = function(e) { 490 | var v = e.either(); 491 | var w = e.other(v); 492 | this.adjList[v].push(e); 493 | this.adjList[w].push(e); 494 | }; 495 | 496 | jss.WeightedGraph = WeightedGraph; 497 | 498 | var WeightedDiGraph = function(V) { 499 | WeightedGraph.call(this, V); 500 | }; 501 | 502 | WeightedDiGraph.prototype = Object.create(jss.WeightedGraph.prototype); 503 | 504 | WeightedDiGraph.prototype.addEdge = function(e) { 505 | var v = e.from(); 506 | this.adjList[v].push(e); 507 | }; 508 | 509 | WeightedDiGraph.prototype.edge = function(v, w) { 510 | var adj_v = this.adjList[v]; 511 | for(var i=0; i < adj_v.length; ++i) { 512 | var x = adj_v[i].other(v); 513 | if(x == w) { 514 | return adj_v[i]; 515 | } 516 | } 517 | return null; 518 | }; 519 | 520 | WeightedDiGraph.prototype.toDiGraph = function() { 521 | var g = new jss.DiGraph(this.V); 522 | for(var v = 0; v < this.V; ++v) { 523 | var adj_v = this.adjList[v]; 524 | for (var i =0; i < adj_v.length; ++i) { 525 | var e = adj_v[i]; 526 | var w = e.other(v); 527 | g.addEdge(v, w); 528 | } 529 | } 530 | return g; 531 | }; 532 | 533 | jss.WeightedDiGraph = WeightedDiGraph; 534 | 535 | var FlowEdge = function(v, w, capacity) { 536 | this.v = v; 537 | this.w = w; 538 | this.capacity = capacity; 539 | this.flow = 0; 540 | }; 541 | 542 | FlowEdge.prototype.residualCapacityTo = function (x) { 543 | if(x == this.v) { 544 | return this.flow; 545 | } else { 546 | return this.capacity - this.flow; 547 | } 548 | }; 549 | 550 | FlowEdge.prototype.addResidualFlowTo = function (x, deltaFlow) { 551 | if(x == this.v) { 552 | this.flow -= deltaFlow; 553 | } else if(x == this.w) { 554 | this.flow += deltaFlow; 555 | } 556 | }; 557 | 558 | FlowEdge.prototype.from = function() { 559 | return this.v; 560 | }; 561 | 562 | FlowEdge.prototype.to = function() { 563 | return this.w; 564 | }; 565 | 566 | FlowEdge.prototype.other = function(x) { 567 | return x == this.v ? this.w : this.v; 568 | } 569 | 570 | 571 | jss.FlowEdge = FlowEdge; 572 | 573 | var FlowNetwork = function(V) { 574 | this.V = V; 575 | this.adjList = []; 576 | this.nodeInfo = []; 577 | for(var v = 0; v < V; ++v) { 578 | this.adjList.push([]); 579 | this.nodeInfo.push({}); 580 | } 581 | }; 582 | 583 | FlowNetwork.prototype.node = function(v) { 584 | return this.nodeInfo[v]; 585 | }; 586 | 587 | FlowNetwork.prototype.edge = function(v, w) { 588 | var adj_v = this.adjList[v]; 589 | for(var i=0; i < adj_v.length; ++i) { 590 | var x = adj_v[i].other(v); 591 | if(x == w) { 592 | return adj_v[i]; 593 | } 594 | } 595 | return null; 596 | }; 597 | 598 | FlowNetwork.prototype.addEdge = function(e) { 599 | var v = e.from(); 600 | this.adjList[v].push(e); 601 | var w = e.other(v); 602 | this.adjList[w].push(e); 603 | }; 604 | 605 | FlowNetwork.prototype.adj = function(v) { 606 | return this.adjList[v]; 607 | }; 608 | 609 | jss.FlowNetwork = FlowNetwork; 610 | 611 | var DepthFirstSearch = function(G, s) { 612 | this.s = s; 613 | var V = G.V; 614 | this.marked = []; 615 | this.edgeTo = []; 616 | for (var v = 0; v < V; ++v) { 617 | this.marked.push(false); 618 | this.edgeTo.push(-1); 619 | } 620 | 621 | this.dfs(G, s); 622 | }; 623 | 624 | DepthFirstSearch.prototype.dfs = function (G, v) { 625 | this.marked[v] = true; 626 | var adj_v = G.adj(v); 627 | for (var i = 0; i < adj_v.length; ++i){ 628 | var w = adj_v[i]; 629 | if (!this.marked[w]){ 630 | this.edgeTo[w] = v; 631 | this.dfs(G, w); 632 | } 633 | } 634 | }; 635 | 636 | DepthFirstSearch.prototype.hasPathTo = function(v) { 637 | return this.marked[v]; 638 | }; 639 | 640 | DepthFirstSearch.prototype.pathTo = function(v) { 641 | var path = new jss.Stack(); 642 | if(v == this.s) return [v]; 643 | 644 | for(var x = v; x != this.s; x = this.edgeTo[x]) { 645 | path.push(x); 646 | } 647 | path.push(this.s); 648 | return path.toArray(); 649 | }; 650 | 651 | jss.DepthFirstSearch = DepthFirstSearch; 652 | 653 | var BreadthFirstSearch = function(G, s) { 654 | var V = G.V; 655 | this.s = s; 656 | 657 | var queue = new jss.Queue(); 658 | queue.enqueue(s); 659 | this.marked = []; 660 | this.edgeTo = []; 661 | 662 | for(var v = 0; v < V; ++v) { 663 | this.marked.push(false); 664 | this.edgeTo.push(-1); 665 | } 666 | 667 | while (!queue.isEmpty()) { 668 | var v = queue.dequeue(); 669 | this.marked[v] = true; 670 | var adj_v = G.adj(v); 671 | for (var i = 0; i < adj_v.length; ++i) { 672 | var w = adj_v[i]; 673 | if(!this.marked[w]){ 674 | this.edgeTo[w] = v; 675 | queue.enqueue(w); 676 | } 677 | } 678 | } 679 | }; 680 | 681 | BreadthFirstSearch.prototype.hasPathTo = function(v) { 682 | return this.marked[v]; 683 | }; 684 | 685 | BreadthFirstSearch.prototype.pathTo = function(v) { 686 | var path = new jss.Stack(); 687 | if(v == this.s) return [v]; 688 | 689 | for(var x = v; x != this.s; x = this.edgeTo[x]) { 690 | path.push(x); 691 | } 692 | path.push(this.s); 693 | return path.toArray(); 694 | }; 695 | 696 | jss.BreadthFirstSearch = BreadthFirstSearch; 697 | 698 | var ConnectedComponents = function(G) { 699 | this.count = 0; 700 | var V = G.V; 701 | this.marked = []; 702 | this.id = []; 703 | for (var v = 0; v < V; ++v) { 704 | this.marked.push(false); 705 | this.id.push(-1); 706 | } 707 | 708 | for (var v = 0; v < V; ++v) { 709 | if(!this.marked[v]){ 710 | this.dfs(G, v); 711 | this.count++; 712 | } 713 | } 714 | }; 715 | 716 | ConnectedComponents.prototype.dfs = function(G, v) { 717 | this.marked[v] = true; 718 | this.id[v] = this.count; 719 | var adj_v = G.adj(v); 720 | 721 | for(var i = 0; i < adj_v.length; ++i){ 722 | var w = adj_v[i]; 723 | if(!this.marked[w]){ 724 | this.dfs(G, w); 725 | } 726 | } 727 | }; 728 | 729 | ConnectedComponents.prototype.componentId = function(v) { 730 | return this.id[v]; 731 | }; 732 | 733 | ConnectedComponents.prototype.componentCount = function(){ 734 | return this.count; 735 | }; 736 | 737 | 738 | jss.ConnectedComponents = ConnectedComponents; 739 | 740 | var TopologicalSort = function(G) { 741 | this.postOrder = new jss.Stack(); 742 | this.marked = []; 743 | var V = G.V; 744 | for (var v = 0; v < V; ++v) { 745 | this.marked.push(false); 746 | } 747 | 748 | for (var v = 0; v < V; ++v) { 749 | if(!this.marked[v]) { 750 | this.dfs(G, v); 751 | } 752 | } 753 | }; 754 | 755 | TopologicalSort.prototype.dfs = function(G, v) { 756 | this.marked[v] = true; 757 | var adj_v = G.adj(v); 758 | for (var i = 0; i < adj_v.length; ++i) { 759 | var w = adj_v[i]; 760 | if(!this.marked[w]){ 761 | this.dfs(G, w); 762 | } 763 | } 764 | this.postOrder.push(v); 765 | }; 766 | 767 | TopologicalSort.prototype.order = function() { 768 | return this.postOrder.toArray(); 769 | }; 770 | 771 | jss.TopologicalSort = TopologicalSort; 772 | 773 | var StronglyConnectedComponents = function(G) { 774 | var V = G.V; 775 | this.count = 0; 776 | this.marked = []; 777 | this.id = []; 778 | 779 | for(var v = 0; v < V; ++v) { 780 | this.marked.push(false); 781 | this.id.push(-1); 782 | } 783 | 784 | var order = new jss.TopologicalSort(G.reverse()).order(); 785 | for( var i = 0; i < order.length; ++i) { 786 | var v = order[i]; 787 | if(!this.marked[v]){ 788 | this.dfs(G, v); 789 | this.count++; 790 | } 791 | } 792 | }; 793 | 794 | StronglyConnectedComponents.prototype.dfs = function (G, v) { 795 | this.marked[v] = true; 796 | this.id[v] = this.count; 797 | var adj_v = G.adj(v); 798 | for (var i = 0; i < adj_v.length; ++i){ 799 | var w = adj_v[i]; 800 | if(!this.marked[w]){ 801 | this.dfs(G, w); 802 | } 803 | } 804 | }; 805 | 806 | 807 | StronglyConnectedComponents.prototype.componentId = function(v) { 808 | return this.id[v]; 809 | }; 810 | 811 | StronglyConnectedComponents.prototype.componentCount = function(){ 812 | return this.count; 813 | }; 814 | 815 | jss.StronglyConnectedComponents = StronglyConnectedComponents; 816 | 817 | var KruskalMST = function(G) { 818 | var V = G.V; 819 | var pq = new jss.MinPQ(function(e1, e2){ 820 | return e1.weight - e2.weight; 821 | }); 822 | for(var v = 0; v < G.V; ++v){ 823 | var adj_v = G.adj(v); 824 | for (var i = 0; i < adj_v.length; ++i) { 825 | var e = adj_v[i]; 826 | if(e.either() != v) { 827 | continue; 828 | } 829 | pq.enqueue(e); 830 | } 831 | } 832 | 833 | this.mst = []; 834 | 835 | var uf = new jss.QuickUnion(V); 836 | while (!pq.isEmpty() && this.mst.length < V-1) { 837 | var e = pq.delMin(); 838 | var v = e.either(); 839 | var w = e.other(v); 840 | 841 | if(!uf.connected(v, w)){ 842 | uf.union(v, w); 843 | this.mst.push(e); 844 | } 845 | } 846 | }; 847 | 848 | 849 | 850 | jss.KruskalMST = KruskalMST; 851 | 852 | var LazyPrimMST = function(G) { 853 | var V = G.V; 854 | this.marked = []; 855 | for( var v = 0; v < V; ++v) { 856 | this.marked.push(false); 857 | } 858 | 859 | this.pq = new jss.MinPQ(function(e1, e2){ 860 | return e1.weight - e2.weight; 861 | }); 862 | 863 | this.mst = []; 864 | 865 | this.visit(G, 0); 866 | 867 | while(!this.pq.isEmpty() && this.mst.length < V-1) { 868 | var e = this.pq.delMin(); 869 | var v = e.either(); 870 | var w = e.other(v); 871 | if(this.marked[v] && this.marked[w]) continue; 872 | this.mst.push(e); 873 | if(!this.marked[v]) this.visit(G, v); 874 | if(!this.marked[w]) this.visit(G, w); 875 | } 876 | }; 877 | 878 | LazyPrimMST.prototype.visit = function(G, v) { 879 | this.marked[v] = true; 880 | var adj_v = G.adj(v); 881 | for (var i = 0; i < adj_v.length; ++i) { 882 | var e = adj_v[i]; 883 | if(!this.marked[e.other(v)]){ 884 | this.pq.enqueue(e); 885 | } 886 | } 887 | }; 888 | 889 | jss.LazyPrimMST = LazyPrimMST; 890 | 891 | var EagerPrimMST = function(G) { 892 | var V = G.V; 893 | this.pq = new jss.IndexMinPQ(V, function(e1, e2) { 894 | return e1.weight - e2.weight; 895 | }); 896 | this.marked = []; 897 | for(var v = 0; v < V; ++v) { 898 | this.marked.push(false); 899 | } 900 | this.mst = []; 901 | this.visit(G, 0); 902 | while(!this.pq.isEmpty()) { 903 | var e = this.pq.minKey(); 904 | var w = this.pq.delMin(); 905 | 906 | this.mst.push(e); 907 | 908 | if(!this.marked[w]){ 909 | this.visit(G, w); 910 | } 911 | 912 | } 913 | }; 914 | 915 | EagerPrimMST.prototype.visit = function(G, v) { 916 | this.marked[v] = true; 917 | var adj_v = G.adj(v); 918 | for(var i = 0; i < adj_v.length; ++i) { 919 | var e = adj_v[i]; 920 | var w = e.other(v); 921 | if(this.marked[w]) continue; 922 | if(this.pq.containsIndex(w)){ 923 | this.pq.decreaseKey(w, e); 924 | } else { 925 | this.pq.insert(w, e); 926 | } 927 | } 928 | }; 929 | 930 | jss.EagerPrimMST = EagerPrimMST; 931 | 932 | var Dijkstra = function(G, s) { 933 | var V = G.V; 934 | this.s = s; 935 | this.marked = []; 936 | this.edgeTo = []; 937 | this.cost = []; 938 | this.pq = new jss.IndexMinPQ(V, function(cost1, cost2){ 939 | return cost1, cost2; 940 | }); 941 | 942 | for(var v =0; v < V; ++v){ 943 | this.marked.push(false); 944 | this.edgeTo.push(null); 945 | this.cost.push(Number.MAX_VALUE); 946 | } 947 | 948 | this.cost[s] = 0; 949 | 950 | this.pq.insert(s, this.cost[s]); 951 | 952 | while(!this.pq.isEmpty()) { 953 | var v = this.pq.delMin(); 954 | this.marked[v] = true; 955 | var adj_v = G.adj(v); 956 | for(var i = 0; i < adj_v.length; ++i) { 957 | var e = adj_v[i]; 958 | this.relax(e); 959 | } 960 | } 961 | 962 | }; 963 | 964 | 965 | 966 | 967 | Dijkstra.prototype.relax = function(e) { 968 | 969 | var v = e.from(); 970 | var w = e.to(); 971 | 972 | if(this.cost[w] > this.cost[v] + e.weight) { 973 | this.cost[w] = this.cost[v] + e.weight; 974 | this.edgeTo[w] = e; 975 | if(this.pq.containsIndex(w)){ 976 | this.pq.decreaseKey(w, this.cost[w]); 977 | } else { 978 | this.pq.insert(w, this.cost[w]); 979 | } 980 | } 981 | }; 982 | 983 | 984 | 985 | Dijkstra.prototype.hasPathTo = function(v) { 986 | return this.marked[v]; 987 | }; 988 | 989 | 990 | Dijkstra.prototype.pathTo = function(v) { 991 | var path = new jss.Stack(); 992 | for(var x = v; x != this.s; x = this.edgeTo[x].other(x)) { 993 | path.push(this.edgeTo[x]); 994 | } 995 | return path.toArray(); 996 | }; 997 | 998 | Dijkstra.prototype.distanceTo = function(v) { 999 | return this.cost[v]; 1000 | }; 1001 | 1002 | 1003 | jss.Dijkstra = Dijkstra; 1004 | 1005 | var BellmanFord = function(G, s) { 1006 | var V = G.V; 1007 | this.s = s; 1008 | this.marked = []; 1009 | this.edgeTo = []; 1010 | this.cost = []; 1011 | 1012 | 1013 | for(var v =0; v < V; ++v){ 1014 | this.marked.push(false); 1015 | this.edgeTo.push(null); 1016 | this.cost.push(Number.MAX_VALUE); 1017 | } 1018 | 1019 | this.cost[s] = 0; 1020 | this.marked[s] = true; 1021 | 1022 | for(var j = 0; j < V; ++j) { 1023 | for(var v = 0; v < V; ++v){ 1024 | var adj_v = G.adj(v); 1025 | for(var i = 0; i < adj_v.length; ++i) { 1026 | var e = adj_v[i]; 1027 | this.relax(e); 1028 | } 1029 | } 1030 | } 1031 | 1032 | }; 1033 | 1034 | BellmanFord.prototype.relax = function(e) { 1035 | 1036 | var v = e.from(); 1037 | var w = e.to(); 1038 | 1039 | if(this.cost[w] > this.cost[v] + e.weight) { 1040 | this.cost[w] = this.cost[v] + e.weight; 1041 | this.marked[w] = true; 1042 | this.edgeTo[w] = e; 1043 | } 1044 | }; 1045 | 1046 | BellmanFord.prototype.hasPathTo = function(v) { 1047 | return this.marked[v]; 1048 | }; 1049 | 1050 | 1051 | BellmanFord.prototype.pathTo = function(v) { 1052 | var path = new jss.Stack(); 1053 | for(var x = v; x != this.s; x = this.edgeTo[x].other(x)) { 1054 | path.push(this.edgeTo[x]); 1055 | } 1056 | return path.toArray(); 1057 | }; 1058 | 1059 | BellmanFord.prototype.distanceTo = function(v) { 1060 | return this.cost[v]; 1061 | }; 1062 | 1063 | jss.BellmanFord = BellmanFord; 1064 | 1065 | var TopologicalSortShortestPaths = function(G, s) { 1066 | var V = G.V; 1067 | this.s = s; 1068 | this.marked = []; 1069 | this.edgeTo = []; 1070 | this.cost = []; 1071 | 1072 | 1073 | for(var v =0; v < V; ++v){ 1074 | this.marked.push(false); 1075 | this.edgeTo.push(null); 1076 | this.cost.push(Number.MAX_VALUE); 1077 | } 1078 | 1079 | this.cost[s] = 0; 1080 | this.marked[s] = true; 1081 | 1082 | var order = new jss.TopologicalSort(G.toDiGraph()).order(); 1083 | 1084 | 1085 | for(var j = 0; j < order.length; ++j){ 1086 | var v = order[j]; 1087 | var adj_v = G.adj(v); 1088 | for(var i = 0; i < adj_v.length; ++i) { 1089 | var e = adj_v[i]; 1090 | this.relax(e); 1091 | } 1092 | } 1093 | 1094 | 1095 | }; 1096 | 1097 | TopologicalSortShortestPaths.prototype.relax = function(e) { 1098 | 1099 | var v = e.from(); 1100 | var w = e.to(); 1101 | 1102 | if(this.cost[w] > this.cost[v] + e.weight) { 1103 | this.cost[w] = this.cost[v] + e.weight; 1104 | this.marked[w] = true; 1105 | this.edgeTo[w] = e; 1106 | } 1107 | }; 1108 | 1109 | TopologicalSortShortestPaths.prototype.hasPathTo = function(v) { 1110 | return this.marked[v]; 1111 | }; 1112 | 1113 | 1114 | TopologicalSortShortestPaths.prototype.pathTo = function(v) { 1115 | var path = new jss.Stack(); 1116 | for(var x = v; x != this.s; x = this.edgeTo[x].other(x)) { 1117 | path.push(this.edgeTo[x]); 1118 | } 1119 | return path.toArray(); 1120 | }; 1121 | 1122 | TopologicalSortShortestPaths.prototype.distanceTo = function(v) { 1123 | return this.cost[v]; 1124 | }; 1125 | 1126 | jss.TopologicalSortShortestPaths = TopologicalSortShortestPaths; 1127 | 1128 | var FordFulkerson = function(G, s, t) { 1129 | this.value = 0; 1130 | var V = G.V; 1131 | var bottle = Number.MAX_VALUE; 1132 | this.marked = null; 1133 | this.edgeTo = null; 1134 | this.s = s; 1135 | this.t = t; 1136 | while(this.hasAugmentedPath(G)){ 1137 | 1138 | for(var x = this.t; x != this.s; x = this.edgeTo[x].other(x)) { 1139 | bottle = Math.min(bottle, this.edgeTo[x].residualCapacityTo(x)); 1140 | } 1141 | 1142 | for(var x = this.t; x != this.s; x = this.edgeTo[x].other(x)) { 1143 | this.edgeTo[x].addResidualFlowTo(x, bottle); 1144 | } 1145 | 1146 | 1147 | this.value += bottle; 1148 | } 1149 | }; 1150 | 1151 | FordFulkerson.prototype.hasAugmentedPath = function(G) { 1152 | var V = G.V; 1153 | this.marked = []; 1154 | this.edgeTo = []; 1155 | for(var v = 0; v < V; ++v) { 1156 | this.marked.push(false); 1157 | this.edgeTo.push(null); 1158 | } 1159 | 1160 | var queue = new jss.Queue(); 1161 | queue.enqueue(this.s); 1162 | 1163 | this.marked[this.s] = true; 1164 | while(!queue.isEmpty()){ 1165 | var v = queue.dequeue(); 1166 | var adj_v = G.adj(v); 1167 | 1168 | for (var i = 0; i < adj_v.length; ++i) { 1169 | var e = adj_v[i]; 1170 | var w = e.other(v); 1171 | if(!this.marked[w] && e.residualCapacityTo(w) > 0){ 1172 | this.edgeTo[w] = e; 1173 | this.marked[w] = true; 1174 | if(w == this.t){ 1175 | return true; 1176 | } 1177 | 1178 | queue.enqueue(w); 1179 | } 1180 | } 1181 | } 1182 | 1183 | return false; 1184 | }; 1185 | 1186 | FordFulkerson.prototype.minCut = function(G) { 1187 | var cuts = []; 1188 | var V = G.V; 1189 | for(var v = 0; v < V; ++v){ 1190 | var adj_v = G.adj(v); 1191 | for(var i = 0; i < adj_v.length; ++i) { 1192 | var e = adj_v[i]; 1193 | if(e.from() == v && e.residualCapacityTo(e.other(v)) == 0) { 1194 | cuts.push(e); 1195 | } 1196 | } 1197 | } 1198 | 1199 | return cuts; 1200 | }; 1201 | 1202 | jss.FordFulkerson = FordFulkerson; 1203 | })(jsgraphs); 1204 | 1205 | var module = module || {}; 1206 | if(module) { 1207 | module.exports = jsgraphs; 1208 | } --------------------------------------------------------------------------------