0


连通块(dfs)java实现

前言

连通块问题属于图的深度优先遍历dfs,本文章通过求连通块的个数简单案例,来介绍dfs解决连通块问题。

例题链接

http://oj.hzjingma.com/p/29?view=classic

例题中给到的是char类型地图,' . ' 代表不通路,' W ' 代表可连通,具体情况根据题目给的进行修改。

什么是连通块

如图整个表格为一个55二维数组,用来表示整个地图,白色填充为二维数组下标,最外层浅绿色代表地图的边界(为什么创建边界下文有提到),较为深颜色的为存放数据的二维数组,即下标(1~4)(1~4)。而颜色最深的块就是连通块,图中给出的就有三个连通块(上下左右连通,不考虑斜对连通)。

具体思路

除了行数列数以及开辟二维数组地图,还需要一个与地图同样大小的二维数组visitied,用来表示当前节点是否已经被访问过了。具体思路同图的dfs类似,当遍历到一个结点为1表示该节点可以连通(根据题目给的可能不同)并且没被访问过就进行深度遍历。

具体看代码。

代码

import java.util.Scanner;
/**
 * 注意本例题中 
 * char[][]map地图   值为' . ' 代表不通,' W '代表可以连通
 * int[][] visitied访问标记,初始值0未访问,1已访问
 * @author lenovo
 *
 */

public class Main {
    static int n,m,ans;
    static char[][] map;
    static int[][] vistied;
    static int[][] step= {{1,0},{0,1},{-1,0},{0,-1}};
    /*
     * 上下左右移动遍历搜索
     *  1 ,0 表示 x + 1 ,y + 0 向右移动,其他同理
     *  如果为八向连通 则加上, { 1, 1 }, { 1, -1 }, { -1, 1 }, { -1, -1 } 代表斜向移动
     */
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        m=sc.nextInt();
        map=new char[n+2][m+2];
        vistied=new int[n+2][m+2];
        //初始化地图,创建边界
        for (int i = 0; i <= n+1; i++) {
            map[i][0] = '.';
            map[i][m+1] = '.';
        }
        for (int i = 0; i <= m+1; i++) {
            map[0][i] = '.';
            map[n+1][i] = '.';
        }
        //录入数据图(1~n)*(1~m)
        for (int i = 1; i <= n; i++) {
            String s=sc.next();
            int k=0;
            for (int j = 1; j <= m; j++) {
                map[i][j]=s.charAt(k++);
            }
        }
        //从1-n 1-m一次遍历整张数据图
        for (int x = 1; x <=n; x++) {
            for (int y =1; y <=m; y++) {
                //如果当前节点为'W'可以连通 并且为被访问则说明存在一个连通块
                if(vistied[x][y] ==0 && map[x][y] == 'W') {
                    ans++;//连接块数量+1
                    vistied[x][y] = 1;//当前节点标记为已经访问,以免重复判断
                    dfs(x,y);//进行深度优先遍历,将与其连通的所有节点都标记为已经访问。
                    //遍历完后从(1,1)到下一个节点(1,2)继续遍历,一次类推,直到所有节点全遍历完。
                }
            }
        }
        System.out.println(ans);
    }
    private static void dfs(int x, int y) {
        /**
         * step.length - 1 = 3
         * 0 1 2 3 四步代表上下左右均走一遍
         */
        for (int i = 0; i <=(step.length - 1); i++) {
            int newx=x+step[i][0]; //x移动
            int newy=y+step[i][1];//y移动
            //如果移动后的节点 为 'W'可连通,并且未访问,则以移动后的节点为起点继续移动
            if(map[newx][newy] =='W' && vistied[newx][newy] ==0) {
                vistied[newx][newy] = 1;//标记为已访问
                dfs( newx, newy);
            }
        }
    }
    
}

注意

   在实际应用时,为了防止当结点位于边界时,例如结点下标为(0,0),其左结点下标为(-1,0),这时-1会越界。因此开辟二维数组的大小总是比题目中给到的n*m多两行,即开辟(n+2)*(m+2)大小的二维数组。

本文转载自: https://blog.csdn.net/qq_52360069/article/details/123449592
版权归原作者 求不脱发 所有, 如有侵权,请联系我们删除。

“连通块(dfs)java实现”的评论:

还没有评论