深度优先搜索
一.基础知识
Depth-First-Search
DFS深度优先搜索
往深处走
先看树
访问顺序12563478
过程:首先访问1,并置1标记已访问;然后访问与a邻接且未被访问的顶点2(FirstNeighbor),标记2为已访问;然后访问与2邻接且未被访问的顶点5,标记5为已访问。此时5没有未被访问过的邻接点,返回上一个访问过的顶点2,访问与其邻接且未被访问的顶点6(NextNeighbor),标记6为已访问…
故深度优先搜索类似于树的先序遍历
二.进阶
再看图
如果先从2开始访问,第一个相连的是1,再看1的第一个邻接点(希望是5)是2,所以需要一个visited数组来记录已经访问过的结点并跳过本次循环,然后通过1的NextNeighbor找到5;同理,后面通过2的NextNeighbor找到6,通过6的NextNeighbor找到3,与3邻接的4号顶点,4号NextNeighbor到7,最后到8,再层层返回。过程中通过函数调用栈实现。
注:可以通过深度优先遍历来判断有向图是否有环(回路):在遍历过程中如果遇到要访问的结点已在栈中就是有环
练习:从3出发DFS
解:3476215退到7,8
即34762158
另外,也可以通过观察邻接表来推算DFS
练习:从1出发DFS
解:12往深走,(21)6,(62)3,(3)4,(43)7,(7346)8,(847),回退,(73468),回退(4378),回退,(3467),回退,(6237),回退,(216),回退,(12)5
即12634785
(矩阵可自己练习)
回顾总结:
(1)同一个图的邻接矩阵表示方式唯一,因此深度优先遍历序列唯一
(2)同一个图的邻接表表示方式不唯一,因此深度优先遍历序列不唯一
DFS初步构建代码
bool visited[MAX_VERTEX_NUM];//访问标记数组
void DFSTraverse(Graph G) {
for (v = 0; v < G.vexnum; ++v)
visit[v] = FALSE;//初始化数组,用FALSE表示未访问的结点
DFS(G,v);
}
void DFS(Graph G, int v) { //从顶点v出发
visit(v);
visited[v] = TRUE;//用TRUE表示已访问
for(w = FirstNeighbor(G, v); w >= 0;w=NextNeighbor(G,v,w))
if (!visited[w])//w为v的尚未访问的邻接顶点
{
DFS(G, w);
}
}
完成了题目要求,但对于非连通图等特殊情况没有考虑到,无法遍历所有顶点
代码优化
bool visited[MAX_VERTEX_NUM];//访问标记数组
void DFSTraverse(Graph G) {
for (v = 0; v < G.vexnum; ++v)
visit[v] = FALSE;//初始化数组,用FALSE表示未访问的结点
for(v=0;v<G.vexnum;++v)//添加代码
if (!visited[v])
{
DFS(G, v);//从v=0开始遍历
}
}
void DFS(Graph G, int v) { //从顶点v出发
visit(v);
visited[v] = TRUE;//用TRUE表示已访问
for(w = FirstNeighbor(G, v); w >= 0;w=NextNeighbor(G,v,w))
if (!visited[w])//w为v的尚未访问的邻接顶点
{
DFS(G, w);
}
}
故:
【无向图】
(1)此代码中DFSTraverse函数中调用DFS的次数正好等于连通分量数
(2)对于连通图,只需调用一次DFS
【有向图】
调用DFS函数的次数需要具体分析
(1)若起始顶点到其他各顶点都有路径,则只需要调用一次DFS函数(例如从7开始1次,从2开始多次)
(2)对于强连通图,从任一结点出发都只需调用1次DFS
三.性能分析
1.空间复杂度:DFS算法是一个递归算法,主要来源于DFS的递归调用,需要借助一个递归工作栈实现
(1)最坏情况(默认):O(|V|)
(2)最好情况:O(1)
2.时间复杂度
时间复杂度=访问各结点所需时间+探索各条边所需时间
邻接矩阵:O(|V²|)
邻接表:O(|V|+|E|)
四.深度优先生成树和生成森林、图树转化
图树转化
(1)从2开始,按照刚刚的访问次序,通过红色的边可以直接转化成树
转化为
(2)即使从同一个顶点开始,也可能得到不一样的深度优先遍历序列,即对应不同的深度优先生成树
转化为
同样
(1)同一个图的邻接矩阵表示方式唯一,因此深度优先生成树唯一
(2)同一个图的邻接表表示方式不唯一,因此深度优先生成树不唯一
注:对连通图调用DFS才能产生深度优先生成树,否则产生的将是深度优先生成森林
转变为