图(Graph)的javascript实现

起因

最近在看《数据结构与算法--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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值