图(Graph)的javascript实现

0

起因

最近在看《数据结构与算法--javascript描述》,然后上npmjs.org去搜索,想找合适的库参考并记录下来,以备以后用时能拿来即用,最没有发现很合自己意的,于是就决定自己一一实现出来。
这是《数据结构与算法--javascript描述》学习笔记的最后一篇了,本阶段学习圆满结束^_^。

npmjs相关库

  • graph;

  • some-graph。

编程思路

  • 深度优先遍历使用递归,但需要设定外部状态数组,因此使用了一个小技巧;

  • 最短路径为不加权的,加权的应该需要经典的Dijkstra算法,以后再继续完善;

  • 注意拓扑排序与深度优先遍历的异同;

  • 以模块模式组织代码;

自己的实现

Graph.js

(function(){
    "use strict";
    function Graph(v){
        this.vertexs = v;
        this.vertexList = [];
        this.edges = 0;
        this.adj = Object.create(null);
        this._vertex_marked = [];
        this._edgeTo = [];          //保存可达路径
    }

    //拓扑排序
    Graph.prototype.topSort = function(){
        var stack = [];
        var visited = [];
        for(var i =0; i < this.vertexs; i++){
            visited[i] = false;
        }
        for(var i = 0; i < this.vertexs; i++){
            if(visited[i] == false){
                this.topSortHelper(i, visited, stack);
            }
        }
        var al = stack.pop();
        while(al != null){
                console.log(this.vertexList[al]);
            al = stack.pop();
        }
    };

    Graph.prototype.topSortHelper = function(v, visited, stack){
        visited[v] = true;
        for(var w in this.adj[v]){
            if(!visited[this.adj[v][w]]){
                this.topSortHelper(this.adj[v][w], visited, stack);
            }
        }
        stack.push(v);
    };

    Graph.prototype.initMarked = function(){
        for(var i = 0; i< this.vertexs; i++){
            this._vertex_marked[i] = false;
        }
    };

    Graph.prototype.pathTo = function(v){
        var start = 0;
        this.bfs(start);
        if(!this.hasPathTo(v)){
            return null;
        }
        var path = [];
        for(var i = v; i != start; i = this._edgeTo[i]){
            path.push(i);
        }
        path.push(start);
        var rs = "";
        while(path.length > 0){
            if(path.length > 1){
                rs += path.pop() + "-";
            }
            else{
                rs += path.pop();
            }
        }
        return rs;
    };

    Graph.prototype.hasPathTo = function(v){
        return this._vertex_marked[v];
    };

    //广度优化遍历,并生成可达路径,为计算无权最短路径提供数据
    Graph.prototype.bfs = function(v){
        this.initMarked();
        var queue = [];
        this._vertex_marked[v] = true;
        queue.push(v);
        while(queue.length > 0){
            var cur = queue.shift();
            console.log("Visited vertex: " + cur);
            for(var w in this.adj[cur]){
                if(!this._vertex_marked[this.adj[cur][w]]) {
                    this._edgeTo[this.adj[cur][w]] = cur;
                    this._vertex_marked[this.adj[cur][w]] = true;
                    queue.push(this.adj[cur][w]);
                }
            }
        }
    };

    //深度优先遍历
    Graph.prototype.dfs = function(v){
        if(arguments[1] == undefined){
            this.initMarked();
        }
        this._vertex_marked[v] = true;
        console.log("Visited vertex: " + v);
        for(var w in this.adj[v]){
            if(!this._vertex_marked[this.adj[v][w]]){
                this.dfs(this.adj[v][w],1);
            }
        }
    };

    Graph.prototype.display = function(){
        for(var i = 0; i < this.vertexs; i++){
            if(this.adj[i] == null){
                console.log(i + " --> This vertex is isolate.")
            }else{
                console.log(i + " --> " + this.adj[i].join(" "))
            }
        }
    };

    Graph.prototype.addEdge = function(v, w){
        if(this.adj[v] == null){
            this.adj[v] = [];
        }
        this.adj[v].push(w);
        if(this.adj[w] == null){
            this.adj[w] = [];
        }
        this.adj[w].push(v);
        this.edges++;
    };

    module.exports = Graph;
})();

源代码地址

https://github.com/zhoutk/js-data-struct
http://git.oschina.net/zhoutk/jsDataStructs

如果觉得我的文章对你有用,请随意赞赏

你可能感兴趣的

莫名小晟 · 2015年11月19日

博主你好,我最近也在看这本书,看到图的时候发现了广度优先的代码会出现死循环,用你的代码试了一下还是会有这个问题,不知道有没有什么解决方案?

回复

zhoutk 作者 · 2015年11月19日

我刚测试了一下,好的啊!
我的测试用例:
var Graph = require('./graph');
var g = new Graph(6);
g.addEdge(1,2);
g.addEdge(2,5);
g.addEdge(1,3);
g.addEdge(1,4);
g.addEdge(0,1);
g.dfs(0);

回复

莫名小晟 · 2015年11月19日

嗯,好吧,那我再看看,应该还是哪里有问题,谢谢

回复

zhoutk 作者 · 2015年11月19日

欢迎交流,你可以把测试代码发给我,我看看是否代码考虑不全面。

回复

莫名小晟 · 2015年11月28日

好吧才看见,我已经发现哪里有问题了,谢谢帮助哈

回复

载入中...