图是网络结构的抽象模型,其是一组由边连接的节点。

由一条边连接在一起的顶点称为相邻顶点; 一个顶点的度是其相邻顶点的数量

路径是顶点v1,v2,v3,...vk的一个连续序列

简单路径要求不包含重复的顶点

如果一个图中不存在环,则称该图是无环的,如果图中每两个顶点间都存在路径,则该图是连通的。

有向图:边有方向;无向图:边没有方向

        

如果图中每两个顶点间在双向上都存在路径,则该图是强连通的。

也有加权的图和未加权的图,带权值的图如下:

 

图的表示:

邻接矩阵:每一个节点都和一个整数关联,该整数作为数组的索引,用一个二维数组来表示顶点间的连接,如果两节点连接,则对应二维数组值为1

 

邻接表:由图中每个顶点的相邻顶点列表组成。可以用数组、链表、散列表或字典来表示相邻顶点列表。

 

关联矩阵:矩阵的行表示顶点,矩阵的列表示边。用二维数组来表示两者的连通性。

 

图类的JavaScript实现:

function Graph() {

    let vertices = []; //list

    let adjList = new Dictionary();

    this.addVertex = function(v){
        vertices.push(v);
        adjList.set(v, []); //initialize adjacency list with array as well;
    };

    this.addEdge = function(v, w){
        adjList.get(v).push(w);
        //adjList.get(w).push(v); //commented to run the improved DFS with topological sorting
    };

    this.toString = function(){
        let s = '';
        for (var i=0; i<vertices.length; i++){
            s += vertices[i] + ' -> ';
            let neighbors = adjList.get(vertices[i]);
            for (var j=0; j<neighbors.length; j++){
                s += neighbors[j] + ' ';
            }
            s += '\n';
        }
        return s;
    };

    let initializeColor = function(){
        let color = [];
        for (var i=0; i<vertices.length; i++){
            color[vertices[i]] = 'white';
        }
        return color;
    };

    this.bfs = function(v, callback){ //广度优先搜索
     //创建一个队列Q;将v标注为被发现的(灰色),并将v入队列Q;
    // 如果Q非空,则进行以下步骤:(1)、将u从Q中出队列 (2)、将标注u为被发现的(灰色)
    //            (3)、将u所有未被访问的邻点(白色)入队列 (4)、将u标注为已被探索的(黑色)

        let color = initializeColor(),
            queue = new Queue();
        queue.enqueue(v);

        while (!queue.isEmpty()){
            let u = queue.dequeue(),
                neighbors = adjList.get(u);
            color[u] = 'grey';
            for ( let i=0; i<neighbors.length; i++){
                let w = neighbors[i];
                if (color[w] === 'white'){
                    color[w] = 'grey';
                    queue.enqueue(w);
                }
            }
            color[u] = 'black';
            if (callback) {
                callback(u);
            }
        }
    };

    this.dfs = function(callback){

        let color = initializeColor();

        for ( let i=0; i<vertices.length; i++){
            if (color[vertices[i]] === 'white'){
                dfsVisit(vertices[i], color, callback);
            }
        }
    };

    var dfsVisit = function(u, color, callback){

        color[u] = 'grey';
        if (callback) {
            callback(u);
        }
        console.log('Discovered ' + u);
        let neighbors = adjList.get(u);
        for ( let i=0; i<neighbors.length; i++){
            let w = neighbors[i];
            if (color[w] === 'white'){
                dfsVisit(w, color, callback);
            }
        }
        color[u] = 'black';
        console.log('explored ' + u);
    };


    this.BFS = function(v){

        let color = initializeColor(),
            queue = new Queue(),
            d = [],
            pred = [];
        queue.enqueue(v);

        for ( let i=0; i<vertices.length; i++){
            d[vertices[i]] = 0;
            pred[vertices[i]] = null;
        }

        while (!queue.isEmpty()){
            let u = queue.dequeue(),
                neighbors = adjList.get(u);
            color[u] = 'grey';
            for (i=0; i<neighbors.length; i++){
                let w = neighbors[i];
                if (color[w] === 'white'){
                    color[w] = 'grey';
                    d[w] = d[u] + 1;
                    pred[w] = u;
                    queue.enqueue(w);
                }
            }
            color[u] = 'black';
        }

        return {
            distances: d,
            predecessors: pred
        };
    };

    let time = 0;
    this.DFS = function(){

        let color = initializeColor(),
            d = [],
            f = [],
            p = [];
        time = 0;

        for ( let i=0; i<vertices.length; i++){
            f[vertices[i]] = 0;
            d[vertices[i]] = 0;
            p[vertices[i]] = null;
        }

        for (i=0; i<vertices.length; i++){
            if (color[vertices[i]] === 'white'){
                DFSVisit(vertices[i], color, d, f, p);
            }
        }

        return {
            discovery: d,
            finished: f,
            predecessors: p
        };
    };

    var DFSVisit = function(u, color, d, f, p){

        console.log('discovered ' + u);
        color[u] = 'grey';
        d[u] = ++time;
        let neighbors = adjList.get(u);
        for (var i=0; i<neighbors.length; i++){
            let w = neighbors[i];
            if (color[w] === 'white'){
                p[w] = u;
                DFSVisit(w,color, d, f, p);
            }
        }
        color[u] = 'black';
        f[u] = ++time;
        console.log('explored ' + u);
    };
}

广度优先搜索(Breadth-First Search, BFS):从指定的第一个顶点开始遍历图,先访问其所有的相邻点,一层一层访问,可以理解为先宽后深地访问顶点。

 

深度优先搜索(Depth-First Search, DFS):从第一个指定的顶点开始遍历图,沿着路经直到这条路径的最后一个顶点被访问,接着园路返回并探索下一条路径,就是先深度后广度地访问顶点。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值