图的深度优先搜索:

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的更多相关文章

  1. 图的深度优先搜索(DFS)和广度优先搜索(BFS)算法

    深度优先(DFS) 深度优先遍历,从初始访问结点出发,我们知道初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接 ...

  2. 【算法导论】图的深度优先搜索遍历(DFS)

    关于图的存储在上一篇文章中已经讲述,在这里不在赘述.下面我们介绍图的深度优先搜索遍历(DFS). 深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj:访问vj之后,又访问vj的一个邻接点, ...

  3. 图的深度优先搜索算法DFS

    1.问题描写叙述与理解 深度优先搜索(Depth First Search.DFS)所遵循的策略.如同其名称所云.是在图中尽可能"更深"地进行搜索. 在深度优先搜索中,对最新发现的 ...

  4. 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)

    深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...

  5. DS图遍历--深度优先搜索

    DS图遍历--深度优先搜索 题目描述 给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始 注意:图n个顶点编号从0到n-1 代码框架如下: 输入 第一行输入t,表示有t个测试实例 第二行输入n, ...

  6. 深度优先搜索DFS和广度优先搜索BFS简单解析

    转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...

  7. 【算法入门】深度优先搜索(DFS)

    深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...

  8. 深度优先搜索 DFS 学习笔记

    深度优先搜索 学习笔记 引入 深度优先搜索 DFS 是图论中最基础,最重要的算法之一.DFS 是一种盲目搜寻法,也就是在每个点 \(u\) 上,任选一条边 DFS,直到回溯到 \(u\) 时才选择别的 ...

  9. 利用广度优先搜索(BFS)与深度优先搜索(DFS)实现岛屿个数的问题(java)

    需要说明一点,要成功运行本贴代码,需要重新复制我第一篇随笔<简单的循环队列>代码(版本有更新). 进入今天的主题. 今天这篇文章主要探讨广度优先搜索(BFS)结合队列和深度优先搜索(DFS ...

随机推荐

  1. Spring的工作原理

    一.什么是Spring (1).Spring真正的精华是它的Ioc模式实现的BeanFactory和AOP,它自己在这个基础上延伸的功能有些画蛇添足. (2). Spring它是一个开源的项目,而且目 ...

  2. JS模块规范:AMD,CMD,CommonJS

    浅析JS模块规范 随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比 ...

  3. python学习-练习题4巩固

    一个数加100后是一个整数的平方,加268后也是一个数的平方,求这个数 分析:这个数加100之后开方是整数,说明int(math.sqrt(a+100))转为整数应该没有小数部分 so:b*b = i ...

  4. 内存管理 malloc free 的实现

    libc 中提供非常好用的  malloc free 功能,如果自己实现一个,应该怎么做. 要实现 malloc free 需要有 可以分配内存使用的堆,和记录内存使用情况的链表. 如下图所示,堆从高 ...

  5. 简单易用的图像解码库介绍 —— stb_image

    原文链接:简单易用的图像解码库介绍 -- stb_image 说到图像解码库,最容易想起的就是 libpng 和 libjpeg 这两个老牌图像解码库了. libpng 和 libjpeg 分别各自对 ...

  6. JS循环嵌套的执行原理

    [逆战班] 循环嵌套是指在一个循环语句中再定义一个循环语句的语法结构,外循环执行一次,内循环全部执行完,直到外循环执行完毕,整个循环结束. while.do.. while和for循环语句都可以进行嵌 ...

  7. python基础(初识)

      Python简介 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心开发一个新的脚本解 ...

  8. Redis为什么这么快?

    Redis为什么这么快?

  9. 聊聊OkHttp实现WebSocket细节,包括鉴权和长连接保活及其原理!

    一.序 OkHttp 应该算是 Android 中使用最广泛的网络库了,我们通常会利用它来实现 HTTP 请求,但是实际上它还可以支持 WebSocket,并且使用起来还非常的便捷. 那本文就来聊聊, ...

  10. 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 ...