JavaScript数据结构之 无向图

/**
 * 无向图
 *
 * 广度优先搜索:初始化每个点的标记为未检查,选一个起始点入队列,贴上待检查标记,
 * 然后该点出队列,寻找所有标记为未检查的相邻点并将其入栈(同时修改其标记为待检查),
 * 对于已经出队列的点,标记为已检查。终止条件:队列为空
 *
 * 深度优先:采用迭代的方式,类似于树的遍历,但是要在遍历过程中检查当前点是否已经并遍历过
 */

function Graph(){
    this.vertices = [];//图的顶点
    this.edgeList = new Map();//采用邻接表保存边,使用的是JavaScript的Map数据结构
}
Graph.prototype = {
    //添加顶点
    addVertex: function(value){
        this.edgeList.set(value, []);
        return this.vertices.push(value);
    },
    //添加边,两个方向都添加
    addEdge: function(value1, value2){
        if(!this.edgeList.get(value1))return false;
        if(!this.edgeList.get(value2))return false;
        this.edgeList.get(value1).push(value2);
        this.edgeList.get(value2).push(value1);
        return true;
    },
    //打印邻接表到控制台
    print: function(){
        var str = "";
        for(let i = this.vertices.length-1;i>=0;i--){
            str += this.vertices[i]+" : ";
            str += this.edgeList.get(this.vertices[i]).join(",");
            str += "\n";
        }
        console.log(str);
        return str;
    },
    //广度优先搜索
    bfs: function(callback,start){
        //distances、predecessors用于统计最短距离
        var distances = [];//距离
        var predecessors = [];//前溯点

        start = start || this.vertices[0];
        var queue = [];
        queue.push(start);//注意,push会改变原数组,但是其返回值是新数组的长度
        var edgeList = this.edgeList;
        var isTrav = new Map();
        this.vertices.forEach(function(v){
            isTrav.set(v,0);
            distances[v] = 0;
            predecessors[v] = null;
        });

        isTrav.set(start, 1);
        while(queue.length>0){
            var u = queue.shift();
            var neighbors = edgeList.get(u);
            for(let i=0;i<neighbors.length;i++){
                var w = neighbors[i];
                if(isTrav.get(w) === 0){
                    isTrav.set(w, 1);
                    queue.push(w);
                    distances[w] = distances[u] + 1;
                    predecessors[w] = u;
                }
            }
            isTrav.set(u, 2);
            callback(u);
        }

        return {
            distances:distances,
            predecessors:predecessors
        };
    },
    //深度优先搜索
    dfs: function(callback, start){
        start = start || this.vertices[0];
        var isTrav = new Map();
        this.vertices.forEach(function(v){
            isTrav.set(v,0);
        });
        this.dfsVisit(start, isTrav, callback);
    },
    dfsVisit: function(n, isTrav, callback){
        isTrav.set(n, 1);
        callback(n);
        var neighbors = this.edgeList.get(n);
        for(let i=0;i<neighbors.length;i++){
            var w = neighbors[i];
            if(isTrav.get(w) == 0){
                this.dfsVisit(w, isTrav, callback);
            }
        }
        isTrav.set(n, 2);
    }
};


var graph = new Graph();
var myVertices = ['A','B','C','D','E','F'];
myVertices.forEach(function(v){
    graph.addVertex(v);
});
graph.addEdge('A','B');
graph.addEdge('A','C');
graph.addEdge('A','D');
graph.addEdge('C','D');
graph.addEdge('C','E');
graph.addEdge('D','E');
graph.addEdge('D','H');
graph.addEdge('B','E');
graph.addEdge('B','F');

console.log("邻接表:");
graph.print();
console.log("广度优先:");
var d = graph.bfs(function(v){console.log(v);});
console.log(d);
console.log("深度优先:");
graph.dfs(function(v){console.log(v);});


输出:

邻接表:
F : B
E : C,D,B
D : A,C,E
C : A,D,E
B : A,E,F
A : B,C,D


广度优先:
A
B
C
D
E
F
{ distances: [ A: 0, B: 1, C: 1, D: 1, E: 2, F: 2 ],
  predecessors: [ A: null, B: 'A', C: 'A', D: 'A', E: 'B', F: 'B' ] }
深度优先:
A
B
E
C
D
F



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值