首页 > 编程语言 >深度优先搜索(DFS) 学习、Java代码实现

深度优先搜索(DFS) 学习、Java代码实现

时间:2023-12-31 13:38:21浏览次数:35  
标签:优先 Java int DFS add 邻接 input public


深度优先搜索(DFS) 的基本思想:从图中的某个顶点v出发,然后依次从未被访问的 v 的邻接点开始深度优先搜索,直至图中所有和 v 路径相通的顶点都被访问,然后选择另外一个没有被访问的顶点开始深度优先搜索。

 1. 概述

 深度优先搜索(DFS) 的基本思想:从图中的某个顶点v出发,然后依次从未被访问的 v 的邻接点开始深度优先搜索,直至图中所有和 v 路径相通的顶点都被访问,然后选择另外一个没有被访问的顶点开始深度优先搜索。

 时间复杂度:

(1)使用数组存储图,时间复杂度 O(n^2), n 为定点数。

(2)使用邻接表存储图,时间复杂度 O (n + e), e 为 边数。

举一个例子:下面这样的一个图。

深度优先搜索(DFS) 学习、Java代码实现_深度优先搜索

对这个图使用深度优先搜索去遍历。

我们使用 v1 作为第一个定点。

# 深度优先搜索 v1 ,v1 未被访问的邻接点为 v2 、v3。

### 深度优先搜索 v2 ,v2 未被访问的邻接点为 v4、 v5。

##### 深度优先搜索 v4 ,v4 未被访问的邻接点为 v8。

####### 深度优先搜索 v8 , v8没有未被访问的邻接点。

##### 深度优先搜索 v5,v5 没有未被访问的邻接点。

### 深度优先搜索 v3,v3 未被访问的邻接点为 v6、v7。

##### 深度优先搜索 v6,v6没有未被访问的邻接点。

##### 深度优先搜索 v7,v7 没有未被访问的邻接点。

深搜遍历顺序 v1 -->  v2 -->  v4  -->  v8  -->  v5  -->  v3  -->   v6  -->   v7。

2. 代码实现

代码实现用的 邻接表,时间复杂度 O (n + e), n 为定点数 , e 为 边数。

package dfs;

import org.omg.PortableInterceptor.INACTIVE;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @Author syrdbt
 * @Date 2019/7/12 21:02
 */
public class MyDFSStudy {
    public List<Integer>[] map; // 存储图
    public boolean vis[]; // vis

    public MyDFSStudy(List<Integer>[] map, int n) {
        this.map = map;
        vis = new boolean[n];
    }

    public void dfs(int i) {
        System.out.print(" " + i + "-->");
        vis[i] = true;
        // 遍历邻接点
        for (int j=0; j<map[i].size(); j++) {
            //System.out.println(map[i].get(j));
            if (vis[map[i].get(j)] == false) {
                this.dfs(map[i].get(j));
            }
        }
    }


    public static void main(String[] args) {
        ArrayList<Integer> []input = new ArrayList[9];
        for (int i=0; i<9; i++) {
            input[i] = new ArrayList<>();
        }
        input[1].add(2);
        input[2].add(1);
        input[1].add(3);
        input[3].add(1);
        input[2].add(4);
        input[4].add(2);
        input[2].add(5);
        input[5].add(2);
        input[3].add(6);
        input[6].add(3);
        input[3].add(7);
        input[7].add(3);
        input[4].add(8);
        input[8].add(4);
        input[5].add(8);
        input[8].add(5);
        input[6].add(7);
        input[7].add(6);
        MyDFSStudy myDFSStudy = new MyDFSStudy(input, 9);
        myDFSStudy.dfs(1);
    }
}

运行截图:

深度优先搜索(DFS) 学习、Java代码实现_System_02

3.  OJ 题: HDU 1241 Oil Deposits

Problem Description

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.

Input

The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket.

Output

For each grid, output the number of distinct oil deposits. Two different pockets are part of the same oil deposit if they are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.

Sample Input

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5 
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

Sample Output

0 1 2 2

 思路:深搜求联通块,对角相邻也算是联通(即8个方向)。

参考代码:

import java.util.Scanner;

/**
 * @Author syrdbt
 * @Date 2019/7/12 17:36
 */
public class Main {
    public char a[][]; //
    public int road[][] = {{-1, -1, -1, 0, 0, 1, 1, 1},
                            {-1, 0, 1, -1, 1, -1, 0, 1}}; //8个方位
    public boolean vis[][];
    int m, n;

    public Main(char[][] a, int m, int n) {
        this.a = a;
        this.m = m;
        this.n = n;
        vis = new boolean[m][n];
    }

    public void dfsLtk(int nowI, int nowJ) {
        vis[nowI][nowJ] = true;

        // 遍历邻接点
        for (int i=0; i<8; i++) {
            int tempI = nowI+road[0][i];
            int tempJ = nowJ+road[1][i];
            if (judge(tempI, tempJ)) {
                dfsLtk(tempI, tempJ);
            }
        }
    }

    public boolean judge(int i, int j) {
        if (i >= 0 && i < m && j >=0 && j < n) {
            if (vis[i][j] == false && a[i][j] == '@')
                return true;
            else
                return false;
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int m, n;
        while (true) {
            m = scanner.nextInt();
            n = scanner.nextInt();
            if (m == 0 && n ==0) {
                break;
            }

            char a[][] = new char[m][n];

            for (int i=0; i<m; i++) {
                String str = scanner.next();
                for (int j=0; j<n; j++) {
                    a[i][j] = str.charAt(j);
//                    System.out.println(a[i][j]);
                }
            }

            Main myDfsStudy = new Main(a, m, n);
            int ans = 0;
            for (int i=0; i<m; i++) {
                for (int j=0; j<n; j++) {
                    if (myDfsStudy.a[i][j] == '@' && myDfsStudy.vis[i][j] == false) {
                        ans ++;
                        myDfsStudy.dfsLtk(i, j);
                    }
                }
            }
            System.out.println(ans);
        }
    }
}

参考文献

  • 数据结构 -  严蔚敏、吴伟民 -  清华大学出版社

标签:优先,Java,int,DFS,add,邻接,input,public
From: https://blog.51cto.com/xuxiangyang/9047856

相关文章

  • Java 自定义注解
    1. 元注解元注解是Java 提供的一些基本注解,使用这些元注解区可疑创建新的注解;可以先大致看一下元注解,然后去看后面自定义注解的例子。元注解有@Retention,@Documented,@Target,@Inherited,@Repeatable 五种。1.1 @Retention@Retention 可以定义注解的生命周期,注解的存活时......
  • Java 自定义类加载器
    1. 系统类加载器系统提供的类加载器有如下三种:启动类加载器, 扩展类加载器,引用程序类加载器。1.1 启动类加载器启动类加载器(BootstrapClassLoader)负责将存放在<JRE_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar......
  • Java递归查询文件下所有的图片,移动到指定文件夹中,分批次建立子文件夹
    1.代码实例将/Users/shiheng/desktop/测试文件目录下的图片(包含子文件夹目录下的图片)移动到了/Users/shiheng/desktop/测试结果目录下,默认不分批次建立子文件夹,重名文件只保存一个,代码如下所示:packagecom.syrdbt.java.study;importjava.io.File;importjava.util.*;/**......
  • 无涯教程-Java 正则 - Matcher reset()函数
    java.util.regex.Matcher.reset()方法重置此匹配器。Matcherreset()-声明publicMatcherreset()Matcherreset()-示例下面的示例显示java.util.regex.Matcher.reset()方法的用法。packagecom.learnfk;importjava.util.regex.Matcher;importjava.util.regex.Pat......
  • 无涯教程-Java 正则 - Matcher int regionStart函数
    java.util.regex.Matcher.regionStart()匹配器区域的起始索引。intregionStart()-声明publicintregionStart()intregionStart()-示例下面的示例显示java.util.regex.Matcher.regionStart()方法的用法。packagecom.learnfk;importjava.util.regex.Matcher;imp......
  • 无涯教程-Java 正则 - String replaceAll(String replacement)函数
    java.util.regex.Matcher.replaceAll(Stringreplacement)方法使用给定的替换字符串替换与该模式匹配的每个子序列。StringreplaceAll-声明publicStringreplaceAll(Stringreplacement)replacement  - 替换字符串。StringreplaceAll-返回值通过用替换字符串替......
  • JavaWebDay10
    开发规范restful表属性状态转换,是一种软件架构风格,注意rest是风格为约定方式可以打破,藐视模块的功能通常使用复数加s,表示此类资源要有一个统一响应数据的格式通常用result实体类来封装当想给参数设置默认值可以使用@requestparam注解后括号接defaultvalue=“1” ......
  • Java 方法
    方法的定义与调用定义:Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法的语法为:修饰符返回值类型方法名(参数类型参数名){ ... 方法体 ... return返回值;}修饰符:可选,告诉编译器如何调用该方法,定义了该方法的访问类型。......
  • 无涯教程-Java 正则 - Matcher static String quoteReplacement(String s)函数
    java.time.Matcher.quoteReplacement(Strings)方法返回指定字符串的文字替换字符串。staticStringquoteReplacement-声明publicstaticStringquoteReplacement(Strings)s  - 要被字符串化的字符串。staticStringquoteReplacement-返回值文字字符串替换。......
  • java的二维数组怎么添加数据
    Java的二维数组怎么添加数据在Java中,二维数组是由多个一维数组组成的,可以看作是一个表格或者矩阵。要向二维数组中添加数据,我们可以使用循环来遍历数组的每个位置,并将数据赋值给对应的元素。创建和初始化二维数组在向二维数组添加数据之前,我们首先需要创建并初始化一个二维数组......