DFS入门(详细讲解+代码模板)

目录

前言
什么是DFS
DFS的过程
DFS能做什么
DFS的模板
	代码模板
	存储方式
		邻接矩阵
		邻接表
DFS扩展算法
练习题

前言

本来这篇博客是一份简单的DFS算法解题报告,在很多方面写的很乱,后面发现越来越多人看到这篇博客,所以决定重写这篇博客,希望能帮助到更多的人,如果觉得你有用支持转载和参考。

什么是DFS

DFS全称Depth-First-Search(深度优先搜索),在数据结构的图中的一个基础算法,是遍历图的常用算法。

DFS的过程

基本步骤:
1.搜索当前节点的所有相邻节点
2.1若有未访问的相邻节点,进入该节点,重复1操作
2.2若没有相邻节点,退回上一个节点
2.3若访问完所有相邻节点,退回上一节点

下面图片简单介绍一下DFS过程(摘至百度)。
在这里插入图片描述

模拟过程
1.从根节点A开始搜索,发现有相邻节点B,进入B

2.进入B后,开始搜索,发现有相邻节点D,进入D
3.进入D后,开始搜索,发现没有相邻节点,退回B
4.回到B后,继续搜索,发现有相邻节点E,进入E
5.进入E后,开始搜索,发现没有相邻节点,退回B
6.回到B后,继续搜索,发现没有相邻节点,退回A
7.回到A后,继续搜索,发现有相邻节点C,进入C

8.进入C后,开始搜索,发现有相邻节点F,进入F
9.进入F后,开始搜索,发现没有相邻节点,退回C
10.回到C后,继续搜索,发现有相邻节点G,进入G
11.进入G后,开始搜索,发现没有相邻节点,退回C
12.回到C后,继续搜索,发现没有相邻节点,退回A
在这里插入图片描述

相信模拟完过程之后,你应该了解DFS的过程了,就是从根节点开始走,走到底,例如从A到D的过程,就是一直走到底。然后再回头访问其他节点。

DFS能做什么

这是遍历图的一个算法,当然是遍历图,可以解决ACM的迷宫类问题,排列组合,八皇后等经典问题等等。

DFS的模板

代码模板:

void dfs(int x){
	if(判断终止条件){
		根据题目条件处理
		return;
	}
	if(判断是否不可能状态){
		减枝
		return;
	}
	if(判断是否越界){
		return;
	}
	for(搜索相邻节点){
		if(没有访问过){
			根据题目条件处理
			v[i]=1;//标记访问过
			dfs(x+1);//继续深搜
			v[i]=0;//恢复标记位
		}
	}
	return;
}

总的来说,DFS三个步骤
1.判断是否终止条件
2.搜索相邻节点,判断是否访问,没有则执行3操作
3.进入该节点,重复2操作,直到所有相邻节点访问完

存储方式:

在图的存储方式中有邻接矩阵,邻接表,根据题目使用不同的存储方式提高效率。

邻接矩阵

邻接矩阵通常使用二维数组来实现,先声明一个二维数组,这里为了方便理解用1表示存在通路,0表示不存在通路(借用一个图来表达一下)
在这里插入图片描述
上面的图我们可以用一个二维数组存储两个点之间是否存在通路
0 1 1 1 1
1 0 1 0 1
1 1 0 1 0
1 0 1 0 1
1 1 0 1 0
如果带权图的话,再另外用一个二维数组存储权就可以了。

邻接表

邻接表通常使用指针来实现,但是指针比较羞涩难懂,所以这里换一种方式实现邻接表
采用数组的方式存储,邻接表有节点,头表和边表,下面分别结合代码介绍。

节点定义:

struct edge{//边节点 
	int value;//权 
	int to;//指向节点 
	int next;
}edges[maxn*2];

头结点定义:

int head[maxn];//存储每个节点的头

链接函数:

void add(int u,int to,int value){
	edges[cnt].to=to; 
	edges[cnt].value=value;
	edges[cnt].next=head[u];//存储着每条边在数组的下标,每次访问i节点,从最后插入的边界往回找 
	head[u]=cnt++;
	edges[cnt].to=u;
	edges[cnt].value=value;
	edges[cnt].next=head[to];
	head[to]=cnt++;
}

下面还是用上面的图片来展示一下存储过程:
假设图转换成下面的输入
1 2
3 4
2 3
1 5
5 4
3 1
4 1
2 5
通过调用add函数,最后变成下面的图(画的有点丑)
在这里插入图片描述
在这里插入图片描述

那这样的邻接表怎么遍历呢

for(int i=head[u];i!=-1;i=edges[i].next){//邻接表,只要next不为-1,即没到头节点 
		to=edges[i].to;
		根据题目条件处理
}

邻接矩阵和邻接表虽然都能存储图,但是在不同的图的存储效率和遍历效率各有千秋,在稀疏图用邻接表存储和遍历比较好,在稠密图邻接矩阵存储和遍历比较好,根据题目条件选择不同的方式可能有质的突破。
其他存储方式,有利用二维数组存储邻接表,或者无权图利用vector容器存储等等,这里过段时间整理好之后会后续补上。

扩展算法(后面整理好也会加上链接):

Tarjan算法(DFS+并查集):处理强连通图,LCA(最近公共祖先)
ST算法(DFS+RMQ)
:LCA 倍增(DFS)

练习题:

DFS入门基础: http://codeup.cn/contest.php?cid=100000608

  • 14
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值