图的深度优先搜索dfs
图的深度优先搜索:
1.将最初访问的顶点压入栈;
2.只要栈中仍有顶点,就循环进行下述操作:
(1)访问栈顶部的顶点u;
(2)从当前访问的顶点u 移动至顶点v 时,将v 压入栈。如果当前顶点u 不存在未访问的相邻矩阵,则将u 从栈中删除;
主要的几个变量:
| color[n] | 用WHITE、GRAY、BLACK 中的一个来表示顶点i 的访问状态 |
| M[n][n] | 邻接矩阵, 如果存在顶点i 到顶点j 的边,则M[i][j]为true |
| Stack S |
栈, 暂存访问过程中的顶点 |
其中color 数组中, 白色代表“未访问的顶点”, 灰色代表“访问过的顶点”(虽然被访问过了,但仍然可能留有通往未访问顶点的边), 黑色代表”访问结束的顶点”;
有俩种方法实现深度优先遍历
(1)用递归实现的深度优先搜索
#include<stdio.h> #define N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2 int n, M[N][N];
int color[N], d[N], f[N], tt;//color[n]表示该顶点访问与否,d[n]表示该顶点的发现时刻 ,f[n]表示该顶点的结束时刻 ,tt表示时间 //用递归函数实现的深度优先搜索
void dfs_visit(int u) {
int v;
color[u] = GRAY;
d[u] = ++tt;
for(v = ; v < n; v++) {
if(M[u][v] == ) continue;
if(color[v] == WHITE)
dfs_visit(v);
}
color[u] = BLACK;
f[u] = ++tt;//访问结束
} void dfs() {
int u;
//初始化
for(u = ; u < n; u++) color[u] = WHITE;
tt = ; //以未访问的u为起点进行深度优先搜索
for(u = ; u < n; u++) {
if(color[u] == WHITE)
dfs_visit(u);
} //输出
for(u = ; u < n; u++) {
printf("%d %d %d\n", u+, d[u], f[u]);
}
} int main() {
int u, v, k, i, j; scanf("%d", &n);
//初始化
for(i = ; i < n; i++) {
for(j = ; j < n; j++) {
M[i][j] = ;
}
}
//输入数据,构造邻接矩阵
for(i = ; i < n; i++) {
scanf("%d %d", &u, &k);
u--;
for(j = ; j < k; j++) {
scanf("%d", &v);
v--;
M[u][v] = ;
}
} dfs(); return ;
} /*
6
1 2 2 3
2 2 3 4
3 1 5
4 1 6
5 1 6
6 0
*/
(2)用栈实现的深度优先搜索
#include<iostream>
#include<stack>
using namespace std; static const int N = ;
static const int WHITE = ;
static const int GRAY = ;
static const int BLACK = ; int n, M[N][N];
int color[N], d[N], f[N], tt;//color[n]表示该顶点访问与否,d[n]表示该顶点的发现时刻 ,f[n]表示该顶点的结束时刻
int nt[N];//记录每个顶点的邻接顶点偏移量,eg:顶点0有俩个顶点1,2;现已经访问过1了,那么, nt[u] = 1; 下次直接访问2 //按编号顺序获取与u相邻的v
int next(int u) {
for(int v = nt[u]; v < n; v++) {
nt[u] = v + ;
if(M[u][v]) return v;
}
return -;
} void dfs_visit(int r) {
for(int i = ; i < n; i++) nt[i] = ; stack <int> S;
S.push(r);
color[r] = GRAY;
d[r] = ++tt; while( !S.empty() ) {
int u = S.top();
int v = next(u);
if(v != -) {
if(color[v] == WHITE) {
color[v] = GRAY;
d[v] = ++tt;
S.push(v);
}
}
else {
S.pop();
color[u] = BLACK;
f[u] = ++tt;
}
}
} void dfs() {
//初始化
for( int i = ; i < n; i++) {
color[i] = WHITE;
nt[i] = ;
}
//设置时间
tt = ; //以未访问的u为起点进行深度优先搜索,设置循环的目的应该是防止该图不是连通图
for(int u = ; u < n; u++) {
if(color[u] == WHITE) dfs_visit(u);
} for(int i = ; i < n; i++) {
cout << i+ << " " << d[i] << " " << f[i] << endl;
}
} int main() {
int u, k, v;
cin >> n; //顶点数 //邻接矩阵置零
for( int i = ; i < n; i++) {
for(int j = ; j < n; j++)
M[i][j] = ;
} //创建邻接矩阵
for(int i = ; i < n; i++) {
cin >> u >> k;//输入顶点和顶点的度
u--;
for(int j = ; j < k; j++) {
cin >> v;
v--;
M[u][v] = ;
}
} dfs(); return ;
} /*
6
1 2 2 3
2 2 3 4
3 1 5
4 1 6
5 1 6
6 0
*/
图的深度优先搜索dfs的更多相关文章
- 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法
深度优先(DFS) 深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接 ...
- 【算法导论】图的深度优先搜索遍历(DFS)
关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...
- 图的深度优先搜索算法DFS
1.问题描写叙述与理解 深度优先搜索(Depth First Search.DFS)所遵循的策略.如同其名称所云.是在图中尽可能"更深"地进行搜索. 在深度优先搜索中,对最新发现的 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- DS图遍历--深度优先搜索
DS图遍历--深度优先搜索 题目描述 给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始 注意:图n个顶点编号从0到n-1 代码框架如下: 输入 第一行输入t,表示有t个测试实例 第二行输入n, ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- 【算法入门】深度优先搜索(DFS)
深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...
- 深度优先搜索 DFS 学习笔记
深度优先搜索 学习笔记 引入 深度优先搜索 DFS 是图论中最基础,最重要的算法之一.DFS 是一种盲目搜寻法,也就是在每个点 \(u\) 上,任选一条边 DFS,直到回溯到 \(u\) 时才选择别的 ...
- 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)
需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...
随机推荐
- Spring的工作原理
一.什么是Spring (1).Spring真正的精华是它的Ioc模式实现的BeanFactory和AOP,它自己在这个基础上延伸的功能有些画蛇添足. (2). Spring它是一个开源的项目,而且目 ...
- JS模块规范:AMD,CMD,CommonJS
浅析JS模块规范 随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比 ...
- python学习-练习题4巩固
一个数加100后是一个整数的平方,加268后也是一个数的平方,求这个数 分析:这个数加100之后开方是整数,说明int(math.sqrt(a+100))转为整数应该没有小数部分 so:b*b = i ...
- 内存管理 malloc free 的实现
libc 中提供非常好用的 malloc free 功能,如果自己实现一个,应该怎么做. 要实现 malloc free 需要有 可以分配内存使用的堆,和记录内存使用情况的链表. 如下图所示,堆从高 ...
- 简单易用的图像解码库介绍 —— stb_image
原文链接:简单易用的图像解码库介绍 -- stb_image 说到图像解码库,最容易想起的就是 libpng 和 libjpeg 这两个老牌图像解码库了. libpng 和 libjpeg 分别各自对 ...
- JS循环嵌套的执行原理
[逆战班] 循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,外循环执行一次,内循环全部执行完,直到外循环执行完毕,整个循环结束. while.do.. while和for循环语句都可以进行嵌 ...
- python基础(初识)
Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心开发一个新的脚本解 ...
- Redis为什么这么快?
Redis为什么这么快?
- 聊聊OkHttp实现WebSocket细节,包括鉴权和长连接保活及其原理!
一.序 OkHttp 应该算是 Android 中使用最广泛的网络库了,我们通常会利用它来实现 HTTP 请求,但是实际上它还可以支持 WebSocket,并且使用起来还非常的便捷. 那本文就来聊聊, ...
- org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout 和 RocketmqRemoting closeChannel: close the connection to remote address[] result: true
org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException: sendDefaultImpl call timeout ...