深度优先算法dfs

2023-10-26

转载https://blog.csdn.net/u014394715/article/details/51192293

 

 

深度优先算法

定义

深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。


简单来说
DFS的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底。 

 

深度与广度的比较

案列:搜索一个图是按照树的层次来搜索的。

我们假设一个节点衍生出来的相邻节点平均的个数是N个,那么当起点开始搜索的时候,队列有一个节点,当起点拿出来后,把它相邻的节点放进去,那么队列就有N个节点,当下一层的搜索中再加入元素到队列的时候,节点数达到了N2,你可以想想,一旦N是一个比较大的数的时候,这个树的层次又比较深,那这个队列就得需要很大的内存空间了。


广度优先搜索

  • 缺点:在树的层次较深并且子节点数较多的情况下,消耗内存十分严重。
  • 优点:能够找到最短路径
  • 适用范围:适用于节点的子节点数量不多,并且树的层次不会太深的情况。

深度优先搜索

优点:内存消耗小,克服广度优先搜索的缺点。因为每次搜的过程,每一层只需维护一个节点

缺点:难以寻找最优解,仅仅只能寻找有解

 

代码

package Test;

import java.util.Stack;

public class DFSTest {

        // 存储节点信息
        private char[] vertices;

        // 存储边信息(邻接矩阵)
        private  int[][] arcs;

        // 图的节点数
        private int vexnum;

        // 记录节点是否已被遍历
        private boolean[] visited;

        // 初始化
        public DFSTest(int[][] arcs,char[] vertices) {
        	//图的节点数
              vexnum = arcs.length;
          	//存储节点信息
              this.vertices = vertices;
              //记录节点是否已被遍历,默认false,数组下标对应相应节点
              visited = new boolean[vexnum];
            //存储边信息(邻接矩阵) 
             this.arcs = arcs;
        }

        // 打印遍历节点
        public void visit(int i){
            System.out.print(vertices[i] + " ");
        }

        // 从第i个节点开始深度优先遍历,获取当前节点的子节点,从左向右的顺序
        public void traverse(int i){
            // 标记第i个节点已遍历
            visited[i] = true;
            // 打印当前遍历的节点
            visit(i);
            // 遍历邻接矩阵中第i个节点的直接联通关系,获取当前节点的子节点
            for(int j=0;j<vexnum;j++){
                // 目标节点与当前节点直接联通,并且该节点还没有被访问,递归
                if(arcs[i][j]==1 && visited[j]==false){
                    traverse(j);
                }
            }
        }

        // 图的深度优先遍历(递归)
        public void DFSTraverse(){
        	// 初始化节点遍历标记,默认设置没有访问
            visited=new boolean[vexnum];
            
            // 从没有被遍历的节点开始深度遍历
            for(int i=0;i<vexnum;i++){
                if(visited[i]==false){
                    // 若是连通图,只会执行一次
                    traverse(i);
                }
            }
        }

        // 图的深度优先遍历(非递归)
        public void DFSTraverse2(){
            // 初始化节点遍历标记,默认设置没有访问
            visited=new boolean[vexnum];
             
            Stack<Integer> s = new Stack<Integer>();
            
            for(int i=0;i<vexnum;i++){
                if(!visited[i]){//如果当前节点没有访问过,添加到栈中
                    //连通子图起始节点
                    s.add(i);
                    do{ 
                        // 出栈
                        int curr = s.pop();
                        // 如果该节点还没有被遍历,则遍历该节点并将相邻节点入栈
                        if(visited[curr]==false){
                            // 遍历并打印
                            visit(curr);
                            //设置该节点以访问
                            visited[curr] = true;
                            // 没遍历的相邻节点入栈(先进后出)
                          for(int j=vexnum-1; j>=0 ; j-- ){
                            	//当前节点的相邻节点,且是没有访问过d
                                if(arcs[curr][j]==1 && visited[j]==false){
                                    s.add(j);
                                }
                            }
                        }
                    }while(!s.isEmpty());
                }
            }
        }

        public static void main(String[] args) {
            
            char[] vertices = {'A','B','C','D','E','F','G','H','I'};
            
            int[][] arcs ={ 
            		{0,1,0,0,0,1,0,0,0}, //A节点的相邻节点设置1
            		{1,0,1,0,0,0,1,0,1},  //B节点的相邻节点设置1
            		{0,1,0,1,0,0,0,0,1},  //C节点的相邻节点设置1
            		{0,0,1,0,1,0,1,1,1}, //D节点的相邻节点设置1
            		{0,0,0,1,0,1,0,1,0},  //E节点的相邻节点设置1
            		{1,0,0,0,1,0,1,0,0},  //F节点的相邻节点设置1
            		{0,1,0,1,0,1,0,1,0},  //G节点的相邻节点设置1
            		{0,0,0,1,1,0,1,0,0},  //H节点的相邻节点设置1
            		{0,1,1,1,0,0,0,0,0},  //I节点的相邻节点设置1
                };
            DFSTest g = new DFSTest(arcs,vertices);
            
           
          

            System.out.print("深度优先遍历(递归):");
            g.DFSTraverse();

            System.out.println();

            System.out.print("深度优先遍历(非递归):");
            g.DFSTraverse2();
        }

}

 

 

 测试结果:

深度优先遍历(递归):A B C D E F G H I 
深度优先遍历(非递归):A B C D E F G H I 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度优先算法dfs 的相关文章

  • Python 邻接矩阵实现无向图、有向图的三种方法,并绘图显示

    网上查了很多资料 发现主要是使用邻接表来实现图 并进行遍历的 而采用邻接矩阵的就非常少 不得已 就只有闭门造车 埋头苦修 小有成果 供后来学习者研究 通过二维数组建立无向图 通过二维数组建立有向图 通过边建立有向图 为方便查看 通过Netw
  • 【模块介绍】WS2812(硬件部分)

    目录 引脚定义 电气属性 电路连接 PCB 软件部分 引脚定义 这是数据手册中引脚定义图和连接方式 可以看出 这个灯是自带芯片控制R G B三色的亮度 可以通过上级的DOUT gt 下级的DIN来使其进行级联 电容官方建议是使用100nF

随机推荐

  • 【元壤教育AI提示工程系列】『KeepChatGPT教程』轻松解决ChatGPT网络报错,畅享无忧沟通!

    元壤教育 中国AIGC提示工程培训的佼佼者 关注 元壤教育 公众号 系统学习AIGC系列课程 提升您10倍生产力 装插件前是这样的 我们使用ChatGPT时 总是因为网络魔法不力的原因导致页面总是报错 如下图所示 装完插件后是这样的 外链图
  • Java整合Redis实现腾讯云短信服务(轻松入门,超详细)

    目录 Java使用腾讯云短信服务 一 短信服务简介 二 准备工作 二 Java操作 三 项目链接 Java使用腾讯云短信服务 一 短信服务简介 首先我们要大致知道短信服务是干什么的 云服务提供商通过短信服务向手机号发送短信 我们可以在云服务
  • PowerShell切换路径

    打开PowerShell 输入以下代码 加将要转换的路径 回车 Set location Path
  • iOS学习笔记一

    文章目录 一 深浅拷贝 二 消息转发机制 三 运行时添加一个类 一 深浅拷贝 浅拷贝只是将指针赋值 而深拷贝进行了内容传递 在Objective C中 NSObject的拷贝方式有两种 copy和mutablecopy 对于NSString
  • 我的2013

    今天是2013年的最后一天 天气格外的晴朗 站在公司的写字楼上 能够看到远处的山水 一直都习惯在一年的最后总结一下 总结自己哪些地方在成长 哪些地方有收获 哪些地方需要改进 但是最近一两年来 却很难回忆一些什么 因为每天都过的差不多 今天下
  • 96道前端面试题+前端常用算法

    这篇文章主要分享一些收集整理的面试题 希望能对大家有所帮助 字节 一面 1 说一下浏览器缓存 2 cookie 与 session 的区别 3 浏览器如何做到 session 的功能的 4 解释一下 csrf 和 xss 5 怎么防止 cs
  • TypeError: load() missing 1 required positional argument: ‘Loader‘

    最近使用yaml load 时报错 TypeError load missing 1 required positional argument Loader 记录原因 YAML 5 1版本后弃用了yaml load file 这个用法 因为
  • 面向对象编程思想

    面向对象编程思想 Object Oriented Programming 面向过程编程思想面向过程核心思想 自顶向下 逐步求精 面向对象编程思想面向对象核心思想 以对象为单位 将解决客观世界问题的方式方法引入到编程领域中 面向对象编程是面向
  • SpringBoot 2.x应用监控配置

    Springboot 2 x应用监控 作用 用于管理 监控应用 暴露自身信息 减少应用系统在采集应用指标的开发量 1 添加依赖
  • 区块链基本概念(一)

    区块链的基本概念 其概念为 区块链是一个去中心化的分布式数据库 改数据库有一串使用密码学方法产生的数据区块有序连接而成 区块中包含有一定时间内产生的无法被篡改的数据记录信息 区块中包含数据记录 当前区块根哈希 Hash 前一区块根哈希 时间
  • Java注解与反射详解

    Java注解与反射详解 注解 Annotations 是Java语言中的一项功能强大的特性 它们提供了一种在源代码中添加元数据的方式 注解可以用于标记 配置和处理程序中的元素 如类 方法 字段等 而反射 Reflection 是Java的一
  • 鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统

    Java版工程项目管理系统 Spring Cloud Spring Boot Mybatis Vue ElementUI 前后端分离 功能清单如下 首页 工作台 待办工作 消息通知 预警信息 点击可进入相应的列表 项目进度图表 选择 总体或
  • [羊城杯 2023] web

    文章目录 D0n t pl4y g4m3 D0n t pl4y g4m3 打开题目 可以判断这里为php Development Server 启动的服务 查询得知 存在 PHP lt 7 4 21 Development Server源码
  • 第5讲 Java注释详解

    您的 关注 和 点赞 是认可 是支持 是动力 如意见相佐 可留言 本人必将竭尽全力试图做到准确和全面 终其一生进行修改补充更新 本文首发在IT羊资源网 IT羊资源网 网址 https www ityangzy com IT羊资源网是IT世界
  • 从零开始编写JNI

    最近项目中用到了JNI 本以为很简单的 没想到花了我一天的时间才搞定 主要是在过程中遇到了一个大坑 下面就详细说说 出现的问题是这样的 代码一运行到System loadLibrary xxx 时 就提示java lang Unsatisf
  • 修改omv的国内镜像服务器,Openmediavault教程 篇二:软件源的更改以及社区插件启用...

    Openmediavault教程 篇二 软件源的更改以及社区插件启用 2021 01 11 17 54 49 6点赞 28收藏 16评论 更改软件源之前需要先将社区插件启用 这样就可以一起将源改变成国内镜像 这样免得后面安装插件的时候又要重
  • ubuntu 20.04 安装 微信,QQ等客户端,一键安装,亲测成功,最新更新,优麒麟

    之前一直使用网页版微信 但是聊天记录完全无法存留 一旦断网就会退出登录 然后每次登录都要确认 很麻烦 要是有ubuntu下的微信客户端就好了 但是并不是所有的客户端都一样好用 博主安装并实测了几个ubuntu下的微信客户端 发现基于wine
  • 第一个爬虫程序,基于requests和BeautifulSoup

    断断续续学了1年多python 最近总算感觉自己入门了 记录下这几天用requests和BeautifulSoup写的爬虫 python的环境是anaconda pycharm 直接上代码 requires authorization 作者
  • Shopify如何使用Google的站长工具

    Shopify在做SEO的时候 Google为我们提供了一个简单的工具 让我们了解它如何看待您的网站 哪些问题可能会影响您的流量 以及您如何改进网站以获得更好的排名和结果 这个工具就是 Google Search Console 这个工具已
  • 深度优先算法dfs

    转载https blog csdn net u014394715 article details 51192293 深度优先算法 定义 深度优先搜索算法 英语 Depth First Search 简称DFS 是一种用于遍历或搜索树或图的算