一、课程目标
- 图的遍历
- 深度优先搜索(DFS)
- 算法实现
- 所有路径
二、目标详解
1、图的遍历
图的遍历:从图的某个顶点出发,按照某种搜索方法沿着图的边访问所有顶点,每个顶点仅访问一次。
遍历得到的顶点的序列,称为图遍历序列。显然不同的搜索方法会得到不同的遍历序列。
有两种搜索方法:
- 深度优先搜索(DFS:Depth First Search)
- 广度优先搜索(BFS:Breadth First Search)
2、深度优先搜索
从某个顶点v0出发,找到其第一个邻接点v1,从v1开始继续进行深度优先搜索,如果某个顶点没有未访问的邻接点,就沿着原路回溯,一直到所有的顶点都被遍历到(既回溯到开始搜索的地方)。
上图从A点出发做dfs搜索(蓝字表示访问,红字表示回溯):
- 访问A点,邻接点有B、F、G,选择B点
- 访问B点,邻接点有C、D,选择C点
- 访问C点,没有邻接点,返回
- 回溯到B点,未访问点有D,选择D点
- 访问D点,邻接点有E,选择E点
- 访问E点,没有邻接点,返回
- 回溯到D点,没有未访问点,返回
- 回溯到B点,没有未访问点,返回
- 回溯到A点,未访问点有F、G,选择F
- 访问F点,没有邻接点,返回
- 回溯到A点,未访问点有G,选择G
- 访问G点,未访问点有H,选择H
- 访问H点,没有邻接点,返回
- 回溯到G点,没有未访问点,返回
- 回溯到A点,没有未访问点,返回
- 回到搜索调用的地方,搜索结束
遍历序列为:ABCDEFGH
理解dfs
:尽可能的远离起始点。
3、算法实现
要点描述
:
- 根据邻接矩阵(或邻接表)能遍历每个点的邻接点
- 已经访问的点,用一个桶数组vis[]记录,防止重复经过
- 一般用递归函数实现递归搜索与无路可走时的回溯
- 也可以用栈(stack)来实现
dfs(顶点) {
记录访问;
for(邻接点)
if (没有访问过)
dfs(邻接点);
}
int main(){
dfs(起始点);
return 0;
}
注意
:dfs遍历时是不需要回溯的,加上回溯就变成了枚举所有的路径
4、所有路径
在dfs里使用vis[N]标记已经访问过的顶点,如果在递归dfs后消除vis[i]的标记,算法就变成了要枚举所有的路径(既回溯算法)。
对于每个路径,需要有获得一个路径状态的明确判断,例如经过的顶点数为n,或者顶点到达某个终点。
然后在这个判断里面,对每个路径状态做判定、求解,例如求最大值之类。
这样子就在dfs的基础上形成了回溯算法:
void dfs(int v) {
if(v == 终点) { //表示到达终点
//对路径做判定、求解
return;
}
// 遍历v连接的所有边(有连接且未访问过),标记、递归、回溯
}