当前位置: 首页 > news >正文

图的遍历:从深度优先到广度优先

图是计算机科学中非常重要的数据结构,广泛应用于许多问题中,如社交网络分析、地图导航、路径查找、网络路由等。而图遍历是图的基本操作之一,用于系统地访问图中的每个节点。图的遍历方式主要有两种:深度优先搜索(DFS)广度优先搜索(BFS)。这篇博客将介绍这两种图的遍历算法,并给出其实现方法和应用场景。

什么是图遍历?

图遍历(Graph Traversal)指的是访问图中所有节点(或边)的一种方法。图的遍历操作不仅需要访问每个节点,还需要确保图中的每一条边也被合适地访问过。根据遍历的顺序和方法,常见的遍历策略有两种:深度优先搜索(DFS)广度优先搜索(BFS)

图的基本表示

在谈到图的遍历之前,我们先简要回顾一下图的常见表示方法。常见的图表示有两种:

  1. 邻接矩阵(Adjacency Matrix):用一个二维数组 adj[i][j] 来表示从节点 i 到节点 j 是否有边。适用于边数较多的图。

  2. 邻接表(Adjacency List):用一个链表或向量来存储每个节点的邻接节点。适用于稀疏图。

深度优先搜索(DFS)

定义

深度优先搜索(DFS)是一种优先遍历图的子节点的遍历方式。它的基本思想是:从一个起始节点出发,尽可能深入地访问未访问的节点,直到没有更多未访问的邻接节点为止,然后回溯到上一个节点,继续尝试访问其他邻接节点。

步骤

  1. 从起始节点开始访问,标记为已访问。

  2. 递归地访问该节点的所有未访问的邻接节点。

  3. 如果一个节点的所有邻接节点都已访问,回溯到父节点。

实现代码(C++)

#include <iostream>
#include <vector>
using namespace std;vector<vector<int>> graph;
vector<bool> visited;void dfs(int node) {visited[node] = true;  // 标记节点为已访问cout << node << " ";    // 访问当前节点// 遍历所有邻接节点for (int neighbor : graph[node]) {if (!visited[neighbor]) {dfs(neighbor);  // 递归访问未访问的邻接节点}}
}int main() {int n, m;cin >> n >> m;  // n 为节点数,m 为边数graph.resize(n + 1);  // 初始化图visited.resize(n + 1, false);  // 初始化访问标记// 输入图的边for (int i = 0; i < m; ++i) {int u, v;cin >> u >> v;graph[u].push_back(v);graph[v].push_back(u);  // 无向图}// 从节点 1 开始进行 DFS 遍历dfs(1);return 0;
}

特点

  • 空间复杂度O(V),其中 V 是图的节点数。递归调用栈的最大深度为 V

  • 时间复杂度O(V + E),其中 E 是图的边数。每个节点和边会被访问一次。

应用场景

  • 路径查找:在某些应用中,如迷宫求解,可以使用 DFS 找到一条路径。

  • 图的连通性:DFS 可以用来判断图是否是连通的,或者求图中的连通分量。

  • 拓扑排序:在有向无环图(DAG)中,DFS 是实现拓扑排序的常用方法。

广度优先搜索(BFS)

定义

广度优先搜索(BFS)是一种层次遍历的策略,它从起始节点开始,首先访问所有与起始节点直接相连的节点,再访问这些节点的邻接节点,以此类推,直到遍历整个图。BFS 使用队列来实现。

步骤

  1. 从起始节点开始访问,标记为已访问。

  2. 将该节点的所有未访问的邻接节点加入队列。

  3. 从队列中取出一个节点,访问它的邻接节点,并将它们加入队列。

  4. 重复步骤3,直到队列为空。

实现代码(C++)

#include <iostream>
#include <vector>
#include <queue>
using namespace std;vector<vector<int>> graph;
vector<bool> visited;void bfs(int start) {queue<int> q;visited[start] = true;q.push(start);while (!q.empty()) {int node = q.front();q.pop();cout << node << " ";  // 访问当前节点// 将未访问的邻接节点加入队列for (int neighbor : graph[node]) {if (!visited[neighbor]) {visited[neighbor] = true;q.push(neighbor);}}}
}int main() {int n, m;cin >> n >> m;  // n 为节点数,m 为边数graph.resize(n + 1);  // 初始化图visited.resize(n + 1, false);  // 初始化访问标记// 输入图的边for (int i = 0; i < m; ++i) {int u, v;cin >> u >> v;graph[u].push_back(v);graph[v].push_back(u);  // 无向图}// 从节点 1 开始进行 BFS 遍历bfs(1);return 0;
}

特点

  • 空间复杂度O(V),队列存储了最坏情况下所有节点。

  • 时间复杂度O(V + E),每个节点和边都会被访问一次。

应用场景

  • 最短路径问题:在无权图中,BFS 用来寻找从起始节点到目标节点的最短路径。

  • 层次遍历:BFS 能够按层次遍历图,适合用于层次分析。

  • 图的广度分析:BFS 可用于分析图的所有邻接关系。

DFS 与 BFS 的比较

特性DFSBFS
遍历方式深入到子节点再回溯按层次逐层访问
使用的数据结构栈(递归调用栈或显式栈)队列
时间复杂度O(V + E)O(V + E)
空间复杂度O(V)O(V)
应用场景路径查找、拓扑排序、连通性最短路径、层次遍历

总结

图的遍历是图论中的基本操作,DFS 和 BFS 各有特点。DFS 更适合用于需要深入探索子节点的场景,而 BFS 更适合层次遍历或寻找最短路径的场景。理解这两种遍历方法及其应用场景,能够帮助我们更好地解决图相关的问题。

希望这篇博客能够帮助你理解图的遍历方法,掌握 DFS 和 BFS 的实现,并能够在实际问题中灵活应用。

http://www.dtcms.com/a/414861.html

相关文章:

  • Java数据结构:ArrayList与顺序表1
  • C语言实战项目:贪吃蛇(1)
  • 鸿蒙应用开发之ArkTs集成AI大模型与Markdown流式渲染教程(API 20)
  • 网站建设服务器环境配置关于网站开发的网店计划书范文
  • LeetCode-hot100——将有序数组转换为二叉搜索树
  • 网站速度对seo的影响修改wordpress登录背景图片
  • Kimi 灰度测试 OK Computer,AI 从 “问答” 迈入 “执行” 新阶段​
  • 什么是 mmap?
  • 民宿客用网络升级方案:从传统到现代化的跃迁
  • 湖南省住房和城乡建设厅老网站做网站分为竞价和优化
  • 品牌创意网站建设韩国手机网站模板
  • 力扣3679. 使库存平衡的最少丢弃次数
  • LeetCode:75.前K个高频元素
  • MySQL 基础指令全解析:从入门到熟练操作
  • 南华 NHZ-03/10/13 型滚筒反力式制动检验台:传统制动检测的核心设备
  • 企业网站开发注册网站开发目录结构
  • 做网站哪个公司好 快选宁陵建站宝互联网行业简介
  • cloudfared 内网穿透通过docker方式遇到的问题
  • 利用汇出与汇入函式协助自动化程式开发
  • iis网站域名访问辽宁工程招标网信息平台
  • 网站开发模板系统myphoto wordpress 国外
  • UART,IIC,SPI串行通信优缺点
  • debian12 安装pve
  • DM存储过程和函数中常用的变量、循环、游标、抛出异常
  • php网站开发怎么样西安网站维护 策划
  • 写csv测试
  • 网站访问不了的原因app运营
  • 一种物联网的节水灌溉系统(论文+源码)
  • 配置AC5(ARM Compiler 5)编译器
  • 合肥中科大网站开发wordpress5.0版本恢复到旧版本