图的深度优先搜索:

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. 并查集(不相交集)的Union操作

    在并查集(不相交集)中附加操作\(Deunion\),它实现的功能是取消最后一次\(Union\)的操作. 实现思想 初始化一个空栈,将每一次的\(Union\)操作的两个集合的根和其值\(Push\ ...

  2. CSS 实现元素较宽不能被完全展示时将其隐藏

    首发于本人的博客 varnull.cn 遇到一个需求,需要实现的样式是固定宽度的容器里一排显示若干个标签,数量不定,每个标签的长度也不定.当到了某个标签不能被完全展示下时则不显示.大致效果如下,标签只 ...

  3. text-decoration与color属性

    text-decoration属性值 如果指定某个标签的text-decoration属性时,希望为其添加多个样式(比如:上划线.下划线.删除线),那么需要把所有的值合并到一个规则中才会生效 p{ t ...

  4. mupdf 基于命令行的 pdf转图片

    下载地址: https://www.mupdf.com/downloads/index.html 使用方法: 打开cmd,切换到mupdf文件路径下,再在命令行中敲入命令  mutool.exe  d ...

  5. Eureka在有虚拟网卡的情况下获取正确的IP

    发现问题 最近项目在Eureka注册时,发现一个问题:注册的IP地址不是 192.168.0.XXX 的网络IP,而是另外一个网段的地址,如图 通过 ipconfig 命令查看本机的IP地址发现,该I ...

  6. SpringBoot入门系列(五)Thymeleaf的常用标签和用法

    前面介绍了Spring Boot 中的整合Thymeleaf .不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/16577 ...

  7. 怎么查看linux文件夹下有多少个文件(mac同样)

    查看目录下有多少个文件及文件夹,在终端输入 ls | wc -w 查看目录下有多少个文件,在终端输入 ls | wc -c 查看文件夹下有多少个文件,多少个子目录,在终端输入 ls -l |wc -l ...

  8. 高可用Keepalived+LVS搭建流程

    本流程搭建1个master,1个backup节点的Keepalived,使用lvs轮询2个节点的服务. 一.使用版本 CentOS 7.7 Keepalived 1.3.5 ipvsadm 1.27( ...

  9. Jira使用说明文档

    1      建立项目 1.1    权限归属 Jira系统管理员 1.2    执行内容 建立项目.工作流分配调整.制定项目负责人及默认经办人 1.3    建立项目过程 登录使用Jira系统管理员 ...

  10. Druid 0.17 入门(3)—— 数据接入指南

    在快速开始中,我们演示了接入本地示例数据方式,但Druid其实支持非常丰富的数据接入方式.比如批处理数据的接入和实时流数据的接入.本文我们将介绍这几种数据接入方式. 文件数据接入:从文件中加载批处理数 ...