美文网首页
11.图的广度优先遍历与无权图的最短路径

11.图的广度优先遍历与无权图的最短路径

作者: 哈哈大圣 | 来源:发表于2019-10-14 22:48 被阅读0次

    图的广度优先遍历与无权图的最短路径

    点击这里,前提知晓...

    一、图的广度优先遍历

    和树的广度优先遍历的思想一样,使用队列作为辅助的数据结构


    广度优先遍历.png

    上述广度优先遍历的结果为0 1 2 5 6 3 4,

    1). 特征

    1. 相对于遍历的起始点的各个点,先遍历的节点的距离要小于等于后遍历的节点!(无权图),所以广度优先遍历可以求出无权图的最短路径。

    二、广度优先遍历与最短路径寻找的实现

    1. 代码实现

    其他类的实现请点击文章开始的链接!

    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Stack;
    import java.util.Vector;
    
    /**
     * @author Liucheng
     * @since 2019-10-13
     */
    public class ShortestPath {
    
        private Graph G;   // 图的引用
        private int s;     // 起始点
        private boolean[] visited;  // 记录dfs的过程中节点是否被访问
        private int[] from;         // 记录路径, from[i]表示查找的路径上i的上一个节点
        private int[] ord;          // 记录路径中节点的次序。ord[i]表示i节点在路径中的次序。
    
        /**
         * 构造函数
         */
        public ShortestPath(Graph G, int s) {
            assert s >= 0 && s < G.V();
    
            this.G = G;     // 图的引用
            this.s = s;     // 起始点
            this.visited = new boolean[G.V()]; // 记录dfs的过程中节点是否被访问
            this.from = new int[G.V()];        // 记录路径, from[i]表示查找的路径上i的上一个节点
            this.ord = new int[G.V()];         // 记录路径中节点的次序。ord[i]表示i节点在路径中的次序。
    
            for (int i = 0; i < G.V(); i++) {
                visited[i] = false;
                from[i] = -1;
                ord[i] = -1;
            }
    
            this.bfs(s);
        }
    
        /**
         * 广度优先遍历
         * 寻路算法,寻找图graph从s点到其他点的路径
         */
        public void bfs(int v) {
            // 广度优先遍历+最短路径算法
            Queue<Integer> q = new LinkedList<>();
            q.add(v);
            visited[v] = true;
            ord[v] = 0;
            while (!q.isEmpty()) {
                int vO = q.remove();
                for (Integer i : G.adj(vO)) {
                    if (!visited[i]) {
                        q.add(i);
                        visited[i] = true;
                        from[i] = vO;
                        ord[i] = ord[vO] + 1;
                    }
                }
            }
        }
    
        /**
         * 查询从s点到w点是否有路径
         */
        public boolean hasPath(int w) {
            assert w >=0 && w < G.V();
    
            return visited[w];
        }
    
        /**
         * 查询从s点到w点的路径,存放在vec中
         */
        public Vector<Integer> path(int w) {
            assert hasPath(w);
    
            Stack<Integer> s = new Stack<>();
            // 通过from数字逆向查找从s到w的路径,存放到栈中
            int p = w;
            while (p != -1) {
                s.push(p);
                p = from[p];
            }
    
            // 从栈中依次取出元素,获得顺序的从s到w的路径
            Vector<Integer> res = new Vector<>();
            while (!s.empty()) {
                res.add(s.pop());
            }
    
            return res;
        }
    
        /**
         * 打印出从s点到w点的路径
         */
        public void showPath(int w) {
            assert w >= 0 && w < G.V();
    
            Vector<Integer> path = this.path(w);
            for (int i = 0; i < path.size(); i++) {
                System.out.print(path.elementAt(i));
                if (i == path.size() - 1) {
                    System.out.println();
                } else {
                    System.out.print(" -> ");
                }
            }
        }
    
        /**
         * 查看从s点到w点的最短路径的长度
         * 若从s到w不可达,返回-1
         */
        public int length(int w) {
            assert w >= 0 && w < G.V();
    
            return ord[w];
        }
    
        /**
         * 测试无权图最短路径算法
         */
        public static void main(String[] args) {
            String filename = Thread.currentThread().getContextClassLoader().getResource("testG.txt").getPath();
            SparseGraph g = new SparseGraph(7, false);
            ReadGraph readGraph = new ReadGraph(g, filename);
            g.show();
    
            // 比较使用深度优先遍历和广度优先遍历获得路径的不同
            // 广度优先遍历获得的是无权图的最短路径
            Path dfs = new Path(g,0);
            System.out.print("DFS : ");
            dfs.showPath(6);
    
            ShortestPath bfs = new ShortestPath(g,0);
            System.out.print("BFS : ");
            bfs.showPath(6);
        }
    }
    
    1. testG.txt文件内容
    7 8
    0 1
    0 2
    0 5
    0 6
    3 4
    3 5
    4 5
    4 6
    
    
    1. 执行结果
    vertex 0:   1   2   5   6   
    vertex 1:   0   
    vertex 2:   0   
    vertex 3:   4   5   
    vertex 4:   3   5   6   
    vertex 5:   0   3   4   
    vertex 6:   0   4   
    DFS : 0 -> 5 -> 3 -> 4 -> 6
    BFS : 0 -> 6
    

    三、图的广度优先遍历的复杂度分析

    1. 稀疏图(邻接表):
      • O(V + E) 表示点的个数加上边的个数
    2. 稠密图(邻接矩阵 :
      • O(V^2) 表示边的次方,因为稠密图计算每一个节点相邻不为空的所有情况

    相关文章

      网友评论

          本文标题:11.图的广度优先遍历与无权图的最短路径

          本文链接:https://www.haomeiwen.com/subject/jbndmctx.html