java--DFS深度搜索方法

该文章详细解释了如何使用JAVA进行深度优先搜索(DFS)遍历无向图,包括节点的概念、DFS的原理、数据结构的设置(如节点数组、二维链接数组、布尔遍历状态数组)以及DFS的递归实现过程。文章还提供了完整的代码示例和理解辅助的示意图。
摘要由CSDN通过智能技术生成

参考文章,原文链接:(5条消息) DFS(深度搜索)无向图遍历(JAVA手把手深入解析)_红目香薰的博客-CSDN博客

部分图片,代码 来自参考文章

DFS(深度搜索)方法理论与理解

节点:即图中包含数字的点,对应代码的数据

深度搜索就是:

从指定节点开始,一直向一个方向走,直到没有路

在有下一级的节点(也就是有链接的节点),我们可以向任意下级节点(没有被遍历过的)出发,还是直到没有下级,

如果没有下一级,就返回,返回到 最近的(上一个) 有未曾遍历的下级节点 的节点,

然后进入到那个未曾遍历的节点方向

输出顺序就是遍历顺序(经过顺序)

下面有手写的流程,可以参考对照,便于理解

DFS方法的实现

数据准备,数据输入

我们需要四个全局变量,全局变量!!!

这里的数据都是以上面的为例子

1,节点数,所有节点的记录

dian即节点(方便理解,随意命名可以),类型为需要的类型,

需要将每一个节点录入该数组,顺序可以随意(下面的二维图转换数组的顺序需要对照这个循序,所以晴考虑一下)

public static String dian[] = { "1", "2", "3", "4", "5", "6", "7" };

2、全节点数,数组长度、节点数量的记录

即所有节点的数量,

下面会按照这个长度来遍历,就是上面数组的长度,

直接定义也许, .length也许

public static int dian_length=dian.length;

3、二维数组,链接关系的记录

这个数组可以存储,每一个节点 所链接的节点都有哪些(包括上、下级);

创建的规则:

,如果有n给节点,就创建n*n的二维数组,

、第n行必须对应 节点数组 的 第n个节点

标注规则:

链接到对应的节点就标注 1

没有链接对应节点就标注 0

如果对应的节点是自身标注 0

看下面就一下明白了,,,,,.

这里用示例包含7个节点,所以7*7的二维数组

    public static int[][] arr= {
            {0,1,1,0,0,0,0},
            {1,0,0,1,1,0,0},
            {1,0,0,0,0,1,0},
            {0,1,0,0,0,0,1},
            {0,1,0,0,0,0,0},
            {0,0,1,0,0,0,0},
            {0,0,0,1,0,0,0},
    };

好像没有关系,其实很容易理解

4、布尔数组,是否遍历的记录

从对方法的理解中,我们知道,再没有下级节点的时候,我们需要返回

并且继续遍历没有遍历的节点

所有我们需要记录节点是否遍历锅,

定义一个布尔类型的数组,记录所有节点的状态

将所有节点初始状态为False(因为初始的布尔数组都是False

再遍历的过程中改为true

我们就知道状态为true的节点就是遍历过的节点

public static boolean[] isfStatus;

数据处理,深度搜索

理解遇到困难可以翻到该部分最下面,有示意图

1、启动,进入递归搜索


/**                                                        
 * 开始DFS
 */                                                        
public static void DFSStart() {                            
    //初始化数组,记录使用过程                                         
    isfStatus = new boolean[dian_length];                     
    //遍历图数组                                                
    for (int i = 0; i < d_length; i++) {                   
        //因为初始的布尔数组都是false,所以只要是false就是没有走过                
        if (isfStatus[i] == false) {                       
            //进度到深度搜索的递归                                   
            DFS(i);                                        
        }                                                  
    }                                                      

实现效果,处理内容

isfStatus = new boolean[dian_length];

初始化状态记录数组,长度为dian_length,状态为false

2、

for循环,判断节点是否遍历过(状态是否为false)

是,继续循环,判断下一节点

否:执行DFS操作,并向下搜索(深度搜索)

2、深度搜索,向下搜索遍历

/**                                                       
 * 递归深搜                                                   
 * @param i                                               
 */                                                       
private static void DFS(int i) {                          
    // TODO Auto-generated method stub                    
    System.out.print(d[i] + " ");                         
    isfStatus[i] = true;                                  
    // 深度搜索子节点·从第一个节点到下一个节点                               
    for (int j = firstValue(i); j >= 0; j = nextValue(i, j)) {
        if (!isfStatus[j]) {                              
            DFS(j);                                       
        }                                                 
    }                                                     
}                                                         

firstValue() 和 nextValue() 是两个自定义函数方法,对应代码在下面,可以先看下面理解,再来看这部分

简单来说,

firstValue() 是对节点对应的数组(二维数组对应 行)遍历的值

nextValue() 是对应的下一节点的值,将要遍历的下一节点

实现效果,处理内容

1、输出当前节点

2、将当前节点的状态改为true,标记为已经遍历过的节点

3、进入当前节点再二维数组里所对应的行,寻找下一级且没有遍历过的节点,进行DFS操作

!isfStatus[j] 如果不是isfStatus[]第j个数据,isfStatus[]是布尔类型数组,所有就是判断是否遍历

3、遍历原理,firstValue() 和 nextValue()的函数部分


/**                                           
 * 第一个连接点                                     
 * @param i                                   
 * @return                                    
 */                                           
private static int firstValue(int i) {        
    for (int j = 0; j < d_length; j++) {      
        if (arr[i][j] > 0) {                  
            return j;                         
        }                                     
    }                                         
    return -1;                                
}                                             
/**                                           
 * 下一个连接点                                     
 * @param i                                   
 * @param j                                   
 * @return                                    
 */                                           
private static int nextValue(int i, int j) {  
    for (int k = (j + 1); k < d_length; k++) {
        if (arr[i][k] == 1) {                 
            return k;                         
        }                                     
    }                                         
    return -1;                                
}    
————————————————
版权声明:本文为CSDN博主「红目香薰」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/feng8403000/article/details/128989010

4、结果输出


public static void main(String[] args) {
    // TODO Auto-generated method stub
    DFSStart();
}

5、示意图,助消化

完整代码

//我写的注释和代码太乱了,还是复制原文了

//是大佬写的有点不好理解,上面是我的理解


public class Demo_def {
    /**
     * 顶点
     */
    public static String d[] = { "1", "2", "3", "4", "5", "6", "7" };
    /**
     * 图转换数组
     */
    public static int[][] arr= {
            {0,1,1,0,0,0,0},
            {1,0,0,1,1,0,0},
            {1,0,0,0,0,1,0},
            {0,1,0,0,0,0,1},
            {0,1,0,0,0,0,0},
            {0,0,1,0,0,0,0},
            {0,0,0,1,0,0,0},
    };
    /**
     * 顶点长度
     */
    public static int d_length=d.length;
    /**
     * 记录每一个节点的遍历过程,走过则记录为true
     */
    public static boolean[] isfStatus;
    /**
     * 开始递归
     */
    public static void DFSStart() {
        //初始化数组,记录使用过程
        isfStatus = new boolean[d_length];
        //遍历图数组
        for (int i = 0; i < d_length; i++) {
            //因为初始的布尔数组都是false,所以只要是false就是没有走过
            if (isfStatus[i] == false) {
                //进度到深度搜索的递归
                DFS(i);
            }
        }
    }
    /**
     * 递归深搜
     * @param i
     */
    private static void DFS(int i) {
        // TODO Auto-generated method stub
        System.out.print(d[i] + " ");
        isfStatus[i] = true;
        // 深度搜索子节点·从第一个节点到下一个节点
        for (int j = firstValue(i); j >= 0; j = nextValue(i, j)) {
            if (!isfStatus[j]) {
                DFS(j);
            }
        }
    }
    /**
     * 第一个连接点
     * @param i
     * @return
     */
    private static int firstValue(int i) {
        for (int j = 0; j < d_length; j++) {
            if (arr[i][j] > 0) {
                return j;
            }
        }
        return -1;
    }
    /**
     * 下一个连接点
     * @param i
     * @param j
     * @return
     */
    private static int nextValue(int i, int j) {
        for (int k = (j + 1); k < d_length; k++) {
            if (arr[i][k] == 1) {
                return k;
            }
        }
        return -1;
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        DFSStart();
    }
 
}
————————————————
版权声明:本文为CSDN博主「红目香薰」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/feng8403000/article/details/128989010
  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
深度优先搜索DFS)是一种常用的图遍历算法,它可以用来遍历或搜索图中的节点。在DFS中,从一个起始节点开始,沿着一条路径尽可能深入地访问节点,直到无法继续深入为止,然后回溯到上一个节点,继续访问其他未被访问的节点,直到所有节点都被访问为止。 在Java中,可以使用递归或者栈来实现DFS算法。下面是一个使用递归实现DFS的示例代码: ```java import java.util.*; class Graph { private int V; // 图中节点的数量 private LinkedList<Integer> adj[]; // 邻接表表示图 // 构造函数 Graph(int v) { V = v; adj = new LinkedList[v]; for (int i = 0; i < v; ++i) adj[i] = new LinkedList(); } // 添加边 void addEdge(int v, int w) { adj[v].add(w); } // 递归实现DFS void DFSUtil(int v, boolean visited[]) { visited[v] = true; System.out.print(v + " "); Iterator<Integer> i = adj[v].listIterator(); while (i.hasNext()) { int n = i.next(); if (!visited[n]) DFSUtil(n, visited); } } // 对外公开的DFS接口 void DFS(int v) { boolean visited[] = new boolean[V]; DFSUtil(v, visited); } } public class Main { public static void main(String args[]) { Graph g = new Graph(4); g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 2); g.addEdge(2, 0); g.addEdge(2, 3); g.addEdge(3, 3); System.out.println("节点2开始的DFS遍历结果:"); g.DFS(2); } } ``` 上述代码中,我们首先定义了一个`Graph`类来表示图,其中使用邻接表来存储图的结构。然后,我们实现了`DFSUtil`方法来递归地进行DFS遍历,并在遍历过中打印节点的值。最后,在`main`方法中创建一个图对象,并调用`DFS`方法来进行DFS遍历。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CLODVEP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值