图的遍历之深度优先搜索(DFS)
深度优先搜索(depth-first search)是对先序遍历(preorder traversal)的推广。”深度优先搜索“,顾名思义就是尽可能深的搜索一个图。想象你是身处一个迷宫的入口,迷宫中的路每一个拐点有一盏灯是亮着的,你的任务是将所有灯熄灭,按照DFS的做法如下:
1. 熄灭你当前所在的拐点的灯
2. 任选一条路向前(深处)走,每经过一个拐点将灯熄灭直到与之相邻的拐点的灯全部熄灭后,原路返回到某个拐点的相邻拐点灯是亮着的,走到灯亮的拐点,重复执行步骤1
3. 当所有灯熄灭时,结束
将上面的例子抽象出来的DFS的算法描述(C伪代码)如下:
- //布尔型数组Visited[]初始化成false
- void DFS(Vetex v)
- {
- Visited[v] = true;
- for each w adjacent to v
- if (!Visited[w])
- DFS(w);
- }
可以看出上述的DFS为递归算法,可以利用栈将其转为非递归。C伪代码如下:
- //布尔型数组Visited[]初始化成false
- void DFS(Vertex v)
- {
- Visited[v] = true;
Stack sta = MakeStack(MAX_SIZE);- Push(sta, v);
- while (!Empty(sta))
- {
- Vertex w = Pop(sta);
- for each u adjacent to w
- {
- if (!Visited[u])
- {
- Push(sta, u);
- Visited[u] = true;
}- }
- }
- }
引理: 若图G是连通的,则通过深度优先搜索可以对它的所有顶点进行标记,并且在算法的执行过程中,它的每一条边至少被查看过一次。
证明: 假设结论不成立,令U表示算法最终未被标记过的顶点的集合。由于G是连通的,因此在U中至少有一个顶点与一个被标记过的顶点相连。但是这种情况不可能成立,因为一旦一个顶点被访问过了,则所有与它相连的未被标记过的顶点也会被访问(从而也被标记)。故所有顶点都会被访问而标记,并且一旦某个顶点被访问,它相连的边就会被查看,所以每条边都将被查看过。
然而,如果一个图G不是连通的,要标记所有顶点,需对DFS稍作修改:若在第一次尝试所有顶点都被标记过,则图是连通的,否则,从任意一个未被标记的顶点开始,再次执行DFS。所以我们可以利用DFS确定一个图是否连通。C伪代码描述上述算法如下:
- /*返回连通成分的数目*/
- int ConnectedComponents ( Graph G )
- {
- int componentNum = ;
- for ( each v in G )
- if ( !visited[V] )
- {
- DFS( v );
- componentNum += ;
- }
- return componentNum;
- }
上述算法的复杂度:
若有N个顶点、 E条边,时间复杂度是
用邻接表存储图,有O(N+E)
用邻接矩阵存储图,有O(N^2)
深度优先搜索的相关练习:
06-图2 Saving James Bond - Easy Version
拓展阅读:
参考资料:
《数据结构与算法分析-C语言描述》
《算法引论》
图的遍历之深度优先搜索(DFS)的更多相关文章
- 采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了)
//采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了) #include <iostream> using namespace std; ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- 用深度优先搜索(DFS)解决多数图论问题
前言 本文大概是作者对图论大部分内容的分析和总结吧,\(\text{OI}\)和语文能力有限,且部分说明和推导可能有错误和不足,希望能指出. 创作本文是为了提供彼此学习交流的机会,也算是作者在忙碌的中 ...
- 【算法入门】深度优先搜索(DFS)
深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...
- 深度优先搜索 DFS 学习笔记
深度优先搜索 学习笔记 引入 深度优先搜索 DFS 是图论中最基础,最重要的算法之一.DFS 是一种盲目搜寻法,也就是在每个点 \(u\) 上,任选一条边 DFS,直到回溯到 \(u\) 时才选择别的 ...
- 图的遍历BFS广度优先搜索
图的遍历BFS广度优先搜索 1. 简介 BFS(Breadth First Search,广度优先搜索,又名宽度优先搜索),与深度优先算法在一个结点"死磕到底"的思维不同,广度优先 ...
- 【PHP数据结构】图的遍历:深度优先与广度优先
在上一篇文章中,我们学习完了图的相关的存储结构,也就是 邻接矩阵 和 邻接表 .它们分别就代表了最典型的 顺序存储 和 链式存储 两种类型.既然数据结构有了,那么我们接下来当然就是学习对这些数据结构的 ...
- 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)
需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...
随机推荐
- FL2440驱动添加(2): RTC(Real time clock)
一,Linux下的时间分为两种,系统时间与硬件时间(RTC芯片): 1,系统时间就是运行系统能够直接看到的时间: 2,硬件时间就是RTC芯片中的时间,断电任然有电池供电: linux系统开机时,会从R ...
- Little Jumper---(三分)
Description Little frog Georgie likes to jump. Recently he have discovered the new playground that s ...
- C语言回滚(三)-指针
#include <stdio.h>#include <stdlib.h> //& 地址运算符 //* 间接运算符 // *的作用 当*后面跟一个指针名或地址的时候, ...
- jQuery coveringBad 效果对比
Covering-Bad 是一个可拉动大小的元素,覆盖在原有的元素上面,从而两者进行对比. 在线实例 实例演示1 实例演示2 使用方法 <div class="covered&q ...
- 数据库表-DD01L DD02L DD03L-保存数据表和域的消息
DD01L 定义域 DD02L SAP-表,记录每张数据库表和自定义表的表相关信息 DD03L 定义字段,记录数据表和自定义表中每个字段相关信息
- SAP ALV标准范例程序介绍
下面介绍几个学习ALV的SAP自带标准程序实例 1. BALVSD06 : Output flights (simple version + save)这是该系列范例最简单的一个,建议以此入门.使用的 ...
- SharePoint 2013 的HTML5特性之响应式布局
今天偶然看到一本书<Pro SharePoint 2013 Branding and Responsive Web Development>,看到SharePoint 2013基于HTML ...
- 在Android开发中使用Ant 一:环境的搭建及入门
配置Ant环境 下载Ant:http://ant.apache.org/bindownload.cgi 在windows上应该选择zip压缩包,将zip压缩包解压到一个目录. 打开系统环境变量,在系统 ...
- 分析实现Android自定义View之扇形图
继承View基类,画了这样的扇形图 直接来步骤吧 (参考了GcsSloop的教程) 1.分析 自定义View需要认真的分析下,里面还是会用到一些数学知识 首先是扇形该怎么表现 1. 扇形的外观是个圆弧 ...
- Windows 7 与 Vmware Ubuntu 15.10_64 共享文件夹
设置共享文件夹 安装/更新最新的vmware-tools 安装 在ubuntu 内部会打开DVD ,里面的压缩包中包含vmware-toole. 先解压 ...