图的遍历[DFS、BFS]

图的遍历

思路:
0. 用邻接矩阵的形式表示图
0.1 所在行数,返回第一个邻接点 [重要]
0.2 在该行数,继续寻找下一个邻接点返回 [重要]
0.3 定义需要使用到的变量 : boolean[] isVisit ; 记录该顶点是否被访问过

  1. 深度优先遍历 [dfs]
    1.1 传入 isVisit 数组、当前所遍历的行 i
    1.2 需要递归
    1.3 输出当前顶点(该行==一个顶点),标记为已经访问过,然后在 该行 i 寻找第一个邻接点
    1.4 判断第一个邻接点是否访问过
    1.4.1 访问过: 在该行 i 继续寻找下一个邻接点
    1.4.2 未访问过: 输出当前顶点(该行),isVisit 标记为已经访问过,递归到该邻接点的行数

  2. 广度优先遍历 [bfs] – 层序遍历-一层一层的遍历下去
    2.1 传入 isVisit 数组、当前所遍历的行 i
    2.2 不需要递归
    2.3 输出当前顶点(该行==一个顶点),isVisit 标记为访问过,将该顶点加入到队列中
    2.4 当队列不为空时循环
    2.5 取出队列的头节点(初始顶点 = = 行),在该行,寻找第一个邻接点,判断该邻接点是否已经被访问过
    2.5.1 访问过: 在该行继续寻找下一个邻接点
    2.5.2 未访问过: 输出该行代表的顶点,isVisit 标记为访问过,将该顶点添加到队列中

在这里插入图片描述



    /**
     *  获取第一个邻接点
     * @param i
     * @return
     */
    public int getFirstVertex(int i){
    
    
        for (int j = 0 ; j < isVisit.length ; j++){
    
    
            if(edges[i][j] > 0){
    
    
                return j;
            }
        }
        return -1;
    }

    /**
     *  获取初顶点的下一个邻接点
     * @param i
     * @return
     */
    public int getAdjoinVertex(int i, int w){
    
    
        for (int j = w + 1 ; j < isVisit.length ; j++){
    
    
            if(edges[i][j] > 0){
    
    
                return j;
            }
        }
        return -1;
    }

    /**
     *   深度优先遍历 图
     * @param isVisit  记录顶点是否访问过的数组
     * @param i        第一个邻接点
     */
    public void dfs(boolean[] isVisit, int i){
    
    
            System.out.print(vertexList.get(i) + "-->");
            isVisit[i] = true;
            int w = getFirstVertex(i);
            while(w != -1){
    
    
                if(!isVisit[w]){
    
    
                    // 如果没有被访问过
                    // 查找下一个邻接点
                    dfs(isVisit, w);
                }
                // 如果 w 已经被访问过了
                // 获取下一个邻接点
                w = getAdjoinVertex(i, w);
            }

    }


    // 重载 dfs
    // 行的递增
    public void dfs(){
    
    
        for (int i = 0; i < vertexList.size() ; i++){
    
    
            if(!isVisit[i]){
    
    
                dfs(isVisit, i);
            }
        }
    }





    /**
     *  某一行的广度优先遍历
     * @param i   第几行
     */
    public void bfs(boolean[] isVisit, int i){
    
    
        int u ;// 表示队列的头节点对应下标
        int w;

        // 如果没有访问过,访问输出
        System.out.print(vertexList.get(i) + "-->");
        isVisit[i] = true;
        // 队列,用来保存广度优先的访问顺序
        LinkedList<Integer> queue = new LinkedList<>();
        // 加入队列中
        queue.addLast(i);

        while( ! queue.isEmpty()){
    
      // 找到了邻接点
            u = queue.removeFirst();  // 取出队列头节点下标
            // 获取第 u 行的邻接点
            w = getFirstVertex(u);
            while(w != -1){
    
    
                //  没有被访问过
                if(!isVisit[w]){
    
    
                    queue.addLast(w);
                    // 进行访问
                    System.out.print(vertexList.get(w) + "-->");
                    isVisit[w] = true;
                }

                // 如果访问过了
                // 则继续在这一行找下一个邻接点
                w = getAdjoinVertex(i, w);  // i 当前的行, w 当前被访问过的邻接点
            }
        }
    }

    // 重载 bfs
    public void bfs(){
    
    

        for (int i = 0; i < vertexList.size() ; i++){
    
    
            if(!isVisit[i]){
    
    
                bfs(isVisit, i);
            }
        }

    }







    public static void main(String[] args) {
    
    
        String[] vertexs = {
    
    "A", "B", "C", "D", "E"};
        Graph g = new Graph(vertexs.length);

        // 插入顶点
        for (int i = 0; i < vertexs.length ; i++){
    
    
            g.insertVertex(vertexs[i]);
        }

        // 插入边
        // A-B  A-C  B-C B-D  B-E
        g.insertEdge(0,1,1); // A-B
        g.insertEdge(0,2,1);
        g.insertEdge(1,2,1);
        g.insertEdge(1,3,1);
        g.insertEdge(1,4,1); // B-E

        g.showGraph();

//        g.dfs();
        g.bfs();
    }


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43765535/article/details/107737953