news 2026/7/3 1:15:54

图的遍历算法:深度优先搜索

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
图的遍历算法:深度优先搜索

图的深度优先搜索(DFS)详解

深度优先搜索(Depth-First Search,DFS)是一种典型的图遍历算法,核心思想是**“先走到底,再回头”**:从起始节点出发,沿着一条路径尽可能深地访问节点,直到无法继续(无未访问的邻接节点),再回溯到上一个节点,探索其他未访问的分支。

资料:https://pan.quark.cn/s/43d906ddfa1bhttps://pan.quark.cn/s/90ad8fba8347https://pan.quark.cn/s/d9d72152d3cf

一、核心概念
  1. 节点状态:通常标记为「未访问」「访问中」「已访问」,避免重复访问和处理环。
  2. 遍历方式
    • 递归实现:利用函数调用栈天然的回溯特性,简洁直观。
    • 非递归实现:手动维护栈结构模拟递归过程,适合处理深度过大的场景(避免栈溢出)。
  3. 适用场景:路径查找、拓扑排序、连通分量、环检测、迷宫求解等。
二、图的存储方式

DFS的实现依赖图的存储结构,常用两种:

  1. 邻接矩阵:二维数组graph[i][j]表示节点ij是否有边(适合稠密图)。
  2. 邻接表:数组+链表/列表,graph[i]存储节点i的所有邻接节点(适合稀疏图,效率更高)。

本文以邻接表为例实现。

三、递归实现 DFS
1. 算法步骤
  • 初始化节点访问状态(如布尔数组visited)。
  • 从起始节点开始,标记为已访问,输出/处理节点。
  • 遍历该节点的所有邻接节点:若未访问,则递归访问该邻接节点。
  • 若图存在多个连通分量,需遍历所有节点,对未访问的节点重复上述步骤。
2. 代码实现(Python)
defdfs_recursive(graph,node,visited):""" 递归实现DFS :param graph: 邻接表表示的图(字典/列表) :param node: 当前访问的节点 :param visited: 记录节点是否被访问的集合/数组 """# 标记当前节点为已访问visited.add(node)print(node,end=" ")# 处理节点(如输出)# 遍历所有邻接节点forneighboringraph[node]:ifneighbornotinvisited:# 递归访问未访问的邻接节点dfs_recursive(graph,neighbor,visited)# 示例:无向图(邻接表)if__name__=="__main__":# 图的邻接表表示(节点为0-4)graph={0:[1,2],1:[0,3,4],2:[0],3:[1],4:[1]}visited=set()# 记录访问过的节点(适合非连续节点)print("DFS递归遍历结果:")dfs_recursive(graph,0,visited)# 从节点0开始遍历
3. 输出结果
DFS递归遍历结果: 0 1 3 4 2
四、非递归(迭代)实现 DFS
1. 算法步骤
  • 初始化栈(存入起始节点)和访问状态。
  • 循环:弹出栈顶节点,若未访问则标记并处理。
  • 将该节点的所有未访问邻接节点压入栈(注意顺序:后压入的先访问,保证DFS顺序)。
  • 重复直到栈为空。
2. 代码实现(Python)
defdfs_iterative(graph,start):""" 非递归实现DFS(栈) :param graph: 邻接表表示的图 :param start: 起始节点 :return: 遍历顺序列表 """visited=set()# 记录已访问节点stack=[start]# 初始化栈,存入起始节点result=[]whilestack:# 弹出栈顶节点node=stack.pop()ifnodenotinvisited:# 标记为已访问,加入结果visited.add(node)result.append(node)# 邻接节点逆序压入栈(保证遍历顺序与递归一致)# 因为栈是后进先出,逆序压入后,正序弹出forneighborinreversed(graph[node]):ifneighbornotinvisited:stack.append(neighbor)returnresult# 示例调用if__name__=="__main__":graph={0:[1,2],1:[0,3,4],2:[0],3:[1],4:[1]}print("\nDFS非递归遍历结果:")print(dfs_iterative(graph,0))
3. 输出结果
DFS非递归遍历结果: [0, 1, 3, 4, 2]
五、处理非连通图

若图包含多个连通分量(无向图),需遍历所有节点,对未访问的节点启动DFS:

defdfs_connected_components(graph):visited=set()components=[]# 存储每个连通分量的遍历结果fornodeingraph:ifnodenotinvisited:component=[]# 递归DFS收集当前连通分量defdfs(node):visited.add(node)component.append(node)forneighboringraph[node]:ifneighbornotinvisited:dfs(neighbor)dfs(node)components.append(component)returncomponents# 示例:非连通图if__name__=="__main__":# 包含两个连通分量:0-1-2 和 3-4graph={0:[1],1:[0,2],2:[1],3:[4],4:[3]}print("\n非连通图的连通分量:")print(dfs_connected_components(graph))

输出:

非连通图的连通分量: [[0, 1, 2], [3, 4]]
六、DFS 特性与复杂度
  1. 时间复杂度
    • 邻接表:O(V + E)(V为节点数,E为边数),每个节点和边仅访问一次。
    • 邻接矩阵:O(V²),需遍历每个节点的所有可能邻接节点。
  2. 空间复杂度
    • 递归:O(V)(递归栈深度,最坏情况为链式图,栈深度=V)。
    • 非递归:O(V)(栈存储节点,最坏情况存入所有节点)。
  3. 特点
    • 不保证找到最短路径(需BFS)。
    • 易实现,适合深度优先的场景(如迷宫、拓扑排序)。
    • 递归实现可能因深度过大导致栈溢出(需改用非递归)。
七、应用场景
  1. 检测图中的环(如判断有向图是否为DAG)。
  2. 拓扑排序(对有向无环图DAG,逆后序遍历DFS结果)。
  3. 寻找两个节点之间的路径。
  4. 求解迷宫问题(深度优先探索所有可能路径)。
  5. 计算图的连通分量(无向图)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 2:25:22

专业图像浏览新选择:这款开源工具如何提升你的工作效率

专业图像浏览新选择:这款开源工具如何提升你的工作效率 【免费下载链接】ImageGlass 🏞 A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass 在数字图像处理日益重要的今天,一款优秀的图…

作者头像 李华
网站建设 2026/7/1 10:47:29

FlightSpy:智能精准自动化机票监控,告别高价困扰

FlightSpy:智能精准自动化机票监控,告别高价困扰 【免费下载链接】flight-spy Looking for the cheapest flights and dont have enough time to track all the prices? 项目地址: https://gitcode.com/gh_mirrors/fl/flight-spy 还在为机票价格…

作者头像 李华
网站建设 2026/7/1 21:24:39

Topit窗口置顶工具:解锁Mac多任务处理新境界

Topit窗口置顶工具:解锁Mac多任务处理新境界 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit 在日常工作中,你是否经常遇到这样的困扰&am…

作者头像 李华
网站建设 2026/7/1 10:47:37

Microsoft Translator集成IndexTTS多语言播报

Microsoft Translator集成IndexTTS多语言播报 在短视频出海、虚拟主播全球化运营和多语种教育内容爆发的今天,创作者面临一个共同难题:如何让一段中文脚本,快速变成一口地道英文、日文或韩文配音,且声音风格统一、情感自然、节奏精…

作者头像 李华
网站建设 2026/7/1 21:02:09

R语言异常值处理陷阱(95%新手都会犯的2个错误)

第一章:R语言异常值处理的核心挑战在数据分析流程中,异常值的存在可能严重扭曲统计模型的推断结果,导致预测偏差或假设检验失效。R语言作为统计计算的重要工具,提供了多种识别与处理异常值的方法,但其灵活性也带来了若…

作者头像 李华
网站建设 2026/7/1 10:47:35

N_m3u8DL-RE:免费快速下载流媒体视频的终极完整指南

N_m3u8DL-RE:免费快速下载流媒体视频的终极完整指南 【免费下载链接】N_m3u8DL-RE 跨平台、现代且功能强大的流媒体下载器,支持MPD/M3U8/ISM格式。支持英语、简体中文和繁体中文。 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE …

作者头像 李华