Depth First Search or DFS for a Graph in Java

2025 年 3 月 28 日 | 阅读 4 分钟

在遍历或搜索图结构时,会使用基本的 **深度优先搜索** (DFS) 方法。它对于许多图论任务来说是一个重要的工具,例如路径查找、循环检测、连通性测试等,因为它会在深入探索每个分支到底,然后再回溯。

DFS 使用隐式或显式堆栈,通过 递归 来操作,实现后进先出 (LIFO) 原则。在本文中,我们将探讨 DFS 算法、其 Java 实现以及它的各种修改。

DFS 算法解释

DFS 算法的工作原理如下:

  1. 从一个节点开始(通常是根节点或任意一个节点)。
  2. 将节点标记为已访问,并将其压入堆栈或使用递归。
  3. 探索当前节点尚未访问过的邻居节点。
  4. 递归地将 DFS 应用于每个未访问的邻居节点,直到没有更多节点可访问为止。
  5. 如果一个节点导致死胡同(所有邻居节点都已访问),则回溯到前一个节点。
  6. 重复此过程,直到所有节点都被访问。

让我们在 Java 程序中实现上述算法。

文件名:DfsInGraph.java

输出

 
Depth First Search starting from vertex 0:
0 1 3 4 2 5   

解释

Graph 类使用邻接表来表示图。每个顶点都有一个名为 LinkedList[] 的数组,其中包含其邻居的列表。addEdge() 函数创建连接两个顶点的边。

由于我们处理的是无向图,因此边会双向添加,从 w 到 v,以及从顶点 v 到 w。为了跟踪哪些顶点已被访问过,DFS() 函数初始化了一个布尔数组 visited[]。

实际的递归遍历由一个名为 DFSUtil() 的辅助函数处理。DFSUtil() 函数将当前节点标记为已访问并打印。接下来,它会递归地探索当前节点的所有未探索过的邻居。

复杂度分析

时间复杂度:基于顶点数 (V) 和边数 (E),DFS 的时间复杂度为 O(V + E)。这是因为遍历会处理每个顶点和边一次。

空间复杂度:由于递归调用堆栈、visited[] 数组、邻接列表和其他组件所需的存储空间,空间复杂度为 O(V)。

DFS 的应用

  1. 迷宫求解和路径查找:在路径查找算法中,当我们需要系统地解决迷宫或查找所有路径时,会用到 DFS。
  2. 循环检测:DFS 可用于查找有向图或无向图中的循环。如果在遍历过程中发现反向边,则存在循环。
  3. 连通分量:即使图表示为不相连的子图集合,DFS 也可用于查找图中的所有连通分量。

结论

由于其递归结构,它对于需要回溯并查看所有可能配置的情况非常有帮助。理解 DFS 对于解决各种与图相关的计算机科学问题至关重要。本文解释了 DFS 的工作原理、应用和复杂度分析,并提供了一个完整的 Java 实现。