数据结构和算法 从0到1:图的深度优先搜索DFS

1、概念

图的深度优先搜索属于图的遍历的一种。

1)图的遍历:

从图中的某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次
注意:树是一种特殊的图,所以树的遍历实际上也可以认为是一种特殊的图的遍历。
在图的遍历过程中,必须记下每个已经访问过的顶点,因此可以设一个辅助数组visited[]来标记顶点是否被访问过
遍历分为:广度优先搜索和深度优先搜索

2)深度优先搜索(Depth-First-Search,DFS)

类似于走迷宫,从迷宫开始一直走走到迷宫出口。
搜索策略是尽可能深地搜索一个图。
必要时要考虑剪枝。DFS需要回溯。

3)深度优先的生成树和生成森林

对于连通图,深度优先搜索会产生一颗深度优先生成树;
对于非连通图产生的是深度优先生成森林
基于邻接表存储的深度优先生成树不是唯一的。

4)算法应用

环路的存在性判断
拓扑排序
强连通分量

2、算法

首先访问图中某一起始点v,然后由v出发,访问与v邻接且未被访问的任一顶点w1,再访问与w1邻接
且未被访问的任一顶点w2…重复上述过程。当不能再继续向下访问时,依次退回到最近被访问的顶点,若它还有邻接顶点未被访问过,则从该点开始继续上述搜索过程,直至图中所有顶点均被访问过为止。
伪代码如下:

bool visited[MAX_VERTEX_NUM];//访问标记数组
void DFSTraverse(Graph G){ //对图G进行深度优先遍历
   for (i = 0;i < G.vexnum;++i) //G.vexnum为顶点的数量
      visited[i] = FALSE;//初始化访问标记数组
   for (i=0;i < G.vexnum;++i)//从0号顶点开始遍历
      if (!vistited[i]) //对每个连通分量调用一次DFS
         DFS(G,i);//vi未被访问过,从vi开始DFS
}
void DFS(Graph G,int v){ //从顶点v出发,深度优先遍历图G
   visit(v); //访问初始顶点v
   visited[v] = TRUE; //对v做已访问标记
   for (w ∈ G.Adj(v)){ // 遍历v的所有邻接顶点
      if (!visited[w]){ //w为v的未被访问的邻接顶点
         DFS(G,w); 
      }
   }
}

举例:
对于下图,运用深度优先搜索
在这里插入图片描述
定义辅助数组:
在这里插入图片描述
伪代码如下:

DFS(G)
输入:图G
输出:祖先数组pred[], 发现时刻d, 结束时刻f
新建一维数组color[1... | V |], pred[1.. | V |], d[1... | V |],f[1... | V |]
// 初始化
for u ∈ V do
    color[u] <- WHITE
    pred[u] <- NULL
end
time <- 0
// 保证搜索完全
for u ∈ V do
    if color[u] == WHITE then
        DFS_Visit(G, u)
    end
end
return pred, d, f

void DFS_Visit(G, v){
    // 修改当前顶点颜色、发现时刻
    color[v] <- GRAY
    time <- time + 1
    d[v] <- time
    // 搜索相邻顶点
    for w ∈ G.Adj[v] do
        if color[w] == WHITE then
            pred[w] <- v
            DFS_Visit(G, w)
        end
    end
    // 结束搜索
    color[v] <- BLACK
    time <- time + 1
    f[v] <- time
}

3、时间复杂度

采用邻接表存储方式时,O(V+E),V、E分别为顶点数、边数
采用邻接矩阵存储方式时,O(V^2)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值