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

【数据结构】图的遍历



快乐的流畅:个人主页


个人专栏:《C游记》《进击的C++》《Linux迷航》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 引言
  • 一、深度优先遍历
    • 1.1 定义
    • 1.2 实现
  • 二、广度优先遍历
    • 2.1 定义
    • 2.2 实现
  • 三、DFS与BFS的对比

引言

前置知识:【数据结构】图的概念和存储结构

一、深度优先遍历

1.1 定义

深度优先遍历(Depth First Search,DFS),是一种从某个顶点开始,沿着一条路径不断深入到未访问的顶点,直到没有新的顶点可以访问为止。然后回溯到前一个顶点,再继续访问其他未被访问的顶点,直到所有顶点都被访问到。

1.2 实现

思路:

  1. 创建vis数组,用于标记已遍历过的顶点,初始为false。
  2. 由于DFS需要递归展开,所以分出一个子函数_DFS。
  3. 进入子函数代表已到达src,所以将vis[srci]标记为true。
  4. 随后for循环查找与当前点相连且没被遍历过的点,再次以新点作为当前点进入子函数,构成重复子问题。
  5. _DFS调用完后,再检查vis数组是否还有未被遍历的点。若有,则再次以此点进行_DFS,防止不连通的区域未被遍历
void _DFS(int srci, vector<bool>& vis)
{vis[srci] = true;cout << "[" << srci << "]" << ":" << _vertexs[srci] << endl;for (int i = 0; i < _vertexs.size(); ++i){if (_edges[srci][i] != W_MAX && !vis[i]){_DFS(i, vis);}}
}void DFS(const V& src)
{int n = _vertexs.size();vector<bool> vis(n, false);int srci = GetIndex(src);_DFS(srci, vis);//防止不连通的区域未被遍历for (int i = 0; i < n; ++i){if (!vis[i]){_DFS(i, vis);}}
}

细节:vis数组的作用,是为了保证遍历的过程中,不遍历相同的点,防止算法时间复杂度大大增加,导致冗余计算。利用vis数组不去遍历相同的点,这个过程又称为剪枝

二、广度优先遍历

2.1 定义

广度优先遍历(Breadth First Search, BFS),是一种从某个顶点开始,先访问当前顶点的所有邻接顶点,然后再依次访问这些邻接顶点的邻接顶点。BFS 是逐层遍历的过程,优先访问离起点较近的顶点。

2.2 实现

思路:

  1. 创建vis数组,用于标记已遍历过的顶点,初始为false。
  2. 创建队列,用于存储待访问的顶点下标。
  3. 初始化,将源点下标存入队列,vis中标记为true。
  4. while循环中,每次取出队头数据并弹出,随后for循环查找与当前点相连且没被遍历过的点,将其存入队列,并且vis中标记为true,构成重复子问题。
void BFS(const V& src)
{int n = _edges.size();vector<bool> vis(n, false);queue<int> q;int srci = GetIndex(src);q.push(srci);vis[srci] = true;int levelSize = 1;while (!q.empty()){//每层分行打印for (int i = 0; i < levelSize; ++i){int front = q.front();q.pop();cout << "[" << front << "]" << ":" << _vertexs[front] << " ";for (int j = 0; j < n; ++j){if (_edges[front][j] != W_MAX && !vis[j]){q.push(j);vis[j] = true;}}}cout << endl;levelSize = q.size();}
}

细节:levelSize的设置,是为了按源点的度从小到大分层打印。每次while循环里用for循环控制打印换行,随后更新levelSize。看似增加一套循环,实际并没有增加时间复杂度。

三、DFS与BFS的对比

以下是 深度优先遍历(DFS)广度优先遍历(BFS) 的对比表格:

特性深度优先遍历(DFS)广度优先遍历(BFS)
使用的数据结构栈(隐式或显式)队列
遍历顺序深入某一条路径,直至没有未访问顶点再回溯按层遍历,从起点逐层向外扩展
适用场景连通分量、拓扑排序、路径搜索最短路径、层次遍历、二分图判定
实现难度简单(递归实现)需要队列,稍复杂
空间复杂度O(V)(递归栈)O(V)(队列)
时间复杂度O(V + E)O(V + E)
  • V 是图中的顶点数,E 是图中的边数。

真诚点赞,手有余香


http://www.mrgr.cn/news/33948.html

相关文章:

  • Project Online 专业版部署方案
  • SBB对象和SBB实体的区别
  • SQL查询中字段选择的两种写法:select * VS select 字段名
  • 软考高级:数据库保持函数依赖和有损无损分解 AI 解读
  • 计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-23
  • 淘客导购系统的分布式存储与管理
  • Vue3通过$emit实现子向父传递数据
  • 【Linux 从基础到进阶】 Google Cloud Platform 配置与管理
  • 网络通信——路由器、交换机、集线器(HUB)
  • EP26 在onLoad周期获取参数获取对应的数据
  • PHP中如何使用三元条件运算符
  • 深入理解Python中的数据结构:deque
  • 告别枯燥:我开发了一个在电脑桌面上使用弹幕来背单词的软件
  • C语言 | Leetcode C语言题解之第429题N叉树的层序遍历
  • C++ | Leetcode C++题解之第430题扁平化多级双向链表
  • git-repo系列教程(6) 在自己服务器上搭建git-repo仓库
  • 2024 离线ASR和TTS推荐与示例
  • 【二等奖论文】2024年华为杯研究生数学建模E题成品论文获取入口
  • Java 每日一刊(第15期):内部类
  • java8新特新(二)