最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 数据结构之图的广度优先搜索(寻找最短路径)

    正文概述 掘金(_乘风_)   2021-08-13   546

    附相关文章的地址:

    • 数据结构之图简介
    • 数据结构之图的创建
    • 数据结构之图的遍历
    • 数据结构之图的广度优先搜索

    上一篇文章中,我们实现了基本的广度优先搜索,也就是BFS的工作原理。而广度优先搜索可以做很多事情,接下来,我们来了解如何使用BFS寻找最短路径。

    使用BFS寻找最短路径

    给定一个图G和源顶点v,找出每个顶点 u 和 v 之间最短路径的距离。

    • 我们以顶点之间边的数量来统计其距离,也就是说两个顶点之间的边的数量越小,代表这两个顶点之间的路径就最短。那么求最短路径也就转换成了求两个顶点之间的边的数量的最小值
    • 从上一篇的广度优先搜索中,我们知道了,广度优先搜索是访问到某个顶点时,会探索它的邻接顶点列表。也就是说,对于给定顶点v,广度优先搜索会先访问其所有的邻接顶点(也就是所有与其距离为1的顶点),接着去访问距离为2的顶点,以此类推。

    数据结构之图的广度优先搜索(寻找最短路径)

    实现

    • 基于上一篇文章中已经实现广度优先搜索的bfs方法:
    this.bfs = function (v) {
        let color = initializeColor();
        let queue = new Queue();
        
        // 创建 d对象,用来存储从顶点v到顶点u的距离d[u]
        let d = {};
        // 创建pred对象,用来存储搜索过程中 顶点v的前一个顶点。即:前溯点pred[u],用来推导出从v到其他每个顶点u的最短路径
        let pred = {};
           
        queue.enqueue(v);
        
        // 同样的,我们遍历图的所有顶点的列表,将每个顶点都其他顶点的距离初始化为0
        for (let i = 0; i < vertices.length; i++) {
            // 记录每个顶点到其他顶点的距离
            d[vertices[i]] = 0;
            pred[vertices[i]] = null;
        }
        
        // 循环队列
        while(!.queue.isEmpty()) {
            // 如果队列非空的话,继续执行以下的操作
            // 移除队列的第一项 u
            let u = queue.dequeue();
            // adjList字典中存储的是顶点和它的邻接顶点列表,所以我们拿到顶点u的邻接列表
            let neighbors = adjList.get(u);
            // 将访问过的顶点u的状态变更为灰色
            color[u] = 'gray'
            // 接着探索 顶点u的邻接列表
            for (let i = 0; i < neighbors.length; i++) {
                // 取出每个邻接顶点
                let w = neighbors[i]
                // 如果该顶点是白色的,则说明未被访问过,那么此时将其状态颜色变为gray,并将其推入队列中,同时改变 w 顶点和 u顶点之间的距离
                if (color[w] === 'white') {
                    color[w] = 'gray'
                    
                    d[w] = d[u] + 1;
                    pred[w] = u;
                    
                    queue.enqueue(w)
                }
            }
            // 当我们将顶点u的所以邻接顶点完全访问完之后,将顶点u的状态变为黑色
            color[u] = 'black';
        }
        // 访问完顶点之后,返回一个对象
        return {
             distances: d,
             predecessors: pred
        }
            
    }
    
    • 改好方法之后,我们调用之后得到以下结果:
    // 起始顶点为A顶点
    const shortestPathA = graph.bfs(myVertices[0]); 
    console.log(shortestPathA);
    
    
    {
           distances: {A: 0, B: 1, C: 1, D: 1, E: 2, F: 2, G: 2, H: 2 , I: 3}, 
           predecessors: {A: null, B: "A", C: "A", D: "A", E: "B", F: "B", G: "C", H: "D", I: "E"}
    }
    

    可以看到我们拿到了 起始顶点为A 到其他顶点的距离的集合,和 每个顶点的前溯顶点的集合。那么我们就可以根据结果得到起始顶点A到其他顶点的最短路径。看下面代码:

    let fromVertex = myVertices[0]; // 即顶点A
    // 遍历图的顶点列表
    for (let i = 1; i < myVertices.length; i++) {
        // 记录下一个顶点
        let toVertex = myVertices[i];
        // 声明path 栈 用来记录路径
        let path = new Stack();
        // 追溯 toVertex 到 fromVertex的路径;变量v赋值为其前溯顶点的值,从而进行反向追溯路径
        for (let v = toVertex; v !== fromVertex; v = shortestPathA.predecessors[v]) {
            // 将顶点v 推入栈中
            path.push(v)
        }
        // 最终将源顶点也推入栈中,得到完整的路径
        path.push(fromVertex);
        // 栈的规则:先进后出,后进先出,所有我们创建变量s,将栈末尾的源顶点赋值给它。
        let s = path.pop();
        // 循环将栈中的顶点取出,拼接到s后面
        while(!path.isEmpty()) {
            s += ` - ${path.pop()}`
        }
        console.log(s)
    }
    

    最终,我们通过上述代码得到了源顶点(也就是起始地顶点A)到图中其他顶点的最短路径。

    写在最后

    不太好理解,需要仔细琢磨。。。


    起源地下载网 » 数据结构之图的广度优先搜索(寻找最短路径)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元