无向图的深度优先遍历与广度优先遍历

news/2024/11/29 11:52:34/

简介

深度优先遍历(Depth-First Search,DFS)和广度优先遍历(Breadth-First Search,BFS)是图遍历算法中常用的两种方法。它们可以用于搜索和遍历图中的顶点,每种方法都有其独特的特点和应用场景。

深度优先遍历

深度优先遍历是一种递归的遍历算法,它从图的某个顶点开始,沿着一条路径尽可能深入地访问顶点,直到无法继续深入为止,然后回溯到上一个顶点,继续访问其他未被访问的顶点,直到所有顶点都被访问完毕。

思路解析:

1. 创建一个visited数组,用于记录顶点是否被访问。
2. 从graph中第一个未被访问顶点v0开始
3. 查找v0的第一个未被访问的邻接点,访问该顶点,并以该顶点为新顶点,依此循环,直到没有未被访问的邻接点。
4. 回到前一个访问过的仍有未被访问的邻接点,继续访问。
5. 重复步骤2,3,直至所有顶点均被访问。

递归实现

示例代码:

#include <iostream>
#include <vector>using namespace std;void dfs(vector<vector<int>> &graph, vector<bool> &visited, int vertex) {visited[vertex] = true;for (int i = 0; i < graph[vertex].size(); i++) {int neighbor = graph[vertex][i];if (!visited[neighbor]) {dfs(graph, visited, neighbor);}}
}void dfsTraversal(vector<vector<int>> &graph) {int numVertices = graph.size();vector<bool> visited(numVertices, false);for (int i = 0; i < numVertices; i++) {if (!visited[i]) {cout << "connected components:";dfs(graph, visited, i);cout << endl;}}
}int main() {vector<vector<int>> graph = {{1, 2},{0},{0},{4},{5},{4}};dfsTraversal(graph);return 0;
}

输出结果(求的连通分量):

connected components:012
connected components:345

总结:使用递归的优点是它更容易实现。但是,也存在一些缺点,如果深度太深,会造成堆栈溢出。这种情况下我们会考虑使用 BFS,或使用显示栈实现 DFS。(其实我们上面使用的是系统提供的隐式栈,也成为调用栈 Call Stack)

显示栈实现

我们只需要修改上面 dfs 函数即可。

示例代码:

void dfs(vector<vector<int>> &graph, vector<bool> &visited, int vertex) {// 将根顶点压栈stack<int> s;s.push(vertex);while (!s.empty()) {// 取栈顶元素int vertex = s.top();s.pop();if (!visited[vertex]) {visited[vertex] = true;cout << vertex << " ";for (int i = 0; i < graph[vertex].size(); i++) {int neighbor = graph[vertex][i];if (!visited[neighbor]) {// 邻接点压栈s.push(neighbor);}}}}
}

总结:使用显示栈实现递归有以下几个优点

- 避免栈溢出:递归算法在处理大规模问题时可能会导致栈溢出的问题,因为每次递归调用都会占用一定的栈空间。使用显示栈可以更好地控制栈的使用,从而避免栈溢出的风险。- 提高性能:递归调用会引入函数调用和返回的开销,包括保存和恢复上下文、参数传递等。使用显示栈可以避免这些开销,因为所有的状态都显式地保存在栈中,而不是通过函数调用和返回来传递。这可以提高算法的性能。- 灵活控制递归过程:使用显示栈可以手动控制递归的深度和顺序。递归函数的执行顺序是由函数调用和返回决定的,而使用显示栈可以在需要时手动推入和弹出栈帧,从而灵活控制递归的深度和顺序。

广度优先遍历

广度优先遍历是一种迭代的遍历算法,它从图的某个顶点开始,先访问该顶点的所有邻居,然后再依次访问邻居的邻居,以此类推,直到遍历完所有可达的顶点。

思路解析:

1. 创建一个visited数组,用于记录已经访问过的顶点。
2. 创建一个队列,并将起始顶点放入队列中。
3. 将起始顶点标记为已访问。
4. 从队列中取出一个顶点,访问该顶点,并将其所有未访问过的邻居顶点放入队列中。
5. 标记刚刚访问过的顶点为已访问。
6. 重复步骤4、5,直到队列为空。

示例代码:

#include <iostream>
#include <vector>
#include <queue>using namespace std;void bfs(vector<vector<int>> &graph, vector<bool> &visited, int start) {visited[start] = true;queue<int> q;q.push(start);while (!q.empty()) {int vertex = q.front();q.pop();cout << vertex << " ";for (int i = 0; i < graph[vertex].size(); i++) {int neighbor = graph[vertex][i];if (!visited[neighbor]) {q.push(neighbor);visited[neighbor] = true;}}}
}void bfsTraversal(vector<vector<int>> &graph) {int numVertices = graph.size();vector<bool> visited(numVertices, false);for (int i = 0; i < numVertices; i++) {if (!visited[i]) {cout << "connected components:";bfs(graph, visited, i);cout << endl;}}
}int main() {vector<vector<int>> graph = {{1, 2},{0},{0},{4},{5},{4}};bfsTraversal(graph);return 0;
}

对比

深度优先遍历(DFS)和广度优先遍历(BFS)是两种常用的图遍历算法,它们在遍历顺序、实现方式和应用场景上有一些区别。

遍历顺序:

  • DFS:深度优先遍历从起始节点开始,沿着一条路径尽可能深入地遍历,直到无法继续深入为止,然后回溯到上一个节点,继续遍历其他路径。DFS会优先探索深度而不是广度。
  • BFS:广度优先遍历从起始节点开始,逐层地遍历图中的节点,先访问离起始节点最近的节点,然后逐渐扩展到离起始节点更远的节点。BFS会优先探索广度而不是深度。

实现方式:

  • DFS:深度优先遍历通常使用递归或栈来实现。递归方式会利用系统的函数调用栈来保存遍历的路径,而栈方式则显式地使用栈数据结构来保存遍历的路径。
  • BFS:广度优先遍历通常使用队列来实现。队列按照节点的到达顺序进行遍历,先进先出的原则确保先访问的节点先被处理。

应用场景:

  • DFS:深度优先遍历常用于寻找图中的路径、拓扑排序、连通性检测等问题。它可以帮助我们在图中找到一条路径,或者判断图是否是连通的。
  • BFS:广度优先遍历常用于寻找图中的最短路径、连通性检测等问题。它可以帮助我们找到起始节点到其他节点的最短路径,并且可以用于解决一些优化问题。

总的来说,DFS和BFS在遍历顺序、实现方式和应用场景上有所不同。DFS更注重深度,而BFS更注重广度。选择使用哪种遍历算法取决于具体的问题需求和图的特点。


http://www.ppmy.cn/news/569350.html

相关文章

最新免费版 Office 全家桶Copilot,Gamma+MindShow 两大ChatGPT AI创意工具GPT-4神器助力高效智能制作 PPT,一键生成,与AI智能对话修改PPT(免安装)

目录 前言ChatGPT MindShow1. 使用ChatGPT工具生成PPT内容2. 使用MindShow工具一键智能制作PPTMindShow简介使用网页版制作pdf转ppt GAMMA AI神器GAMMA.app介绍注册 decks操作Guided 指导Text to deck 文本到PPTpdf转ppt协同操作其它 参考资料其它资料下载 前言 2023年3月&am…

Adobe CC 全系列官网下载地址

Adobe CC 全系列官网下载地址 产品WindowsMac OSPhotoshop CCWindows&#xff08;32 位&#xff09;| Windows&#xff08;64 位&#xff09;Mac OS&#xff08;64 位&#xff09;Lightroom CCWindows&#xff08;64 位&#xff09;Mac OS&#xff08;64 位&#xff09;Lightro…

office2019下载

中文说明&#xff1a;专业增强版/零售版/32位64位二合一镜像 文件名称&#xff1a;ProPlus2019Retail.img文件大小&#xff1a;3.51GB SHA1&#xff1a;d850365b23e1e1294112a51105a2892b2bd88eb9 SHA256&#xff1a;f5bea5517a3879792c39127db77aa7e766b4a9897bf52bed0c7e5dc7…

Adobe考试

Adobe考试又称为Adobe国际认证和Adobe认证考试&#xff0c;Adobe国际认证(英文:Adobe Certified Professional)是Adobe公司CEO签发的权威国际认证体系,旨在为用户提供Adobe软件的专业认证。 Adobe考试覆盖了各种Adobe软件&#xff0c;包括Photoshop、Illustrator、InDesign、P…

Adobe Audition CS6 下载与安装教程

文章目录 Adobe Audition CS6 简介&#xff08;一&#xff09;Adobe Audition cs6软件功能&#xff08;二&#xff09;Adobe Audition cs6软件特色&#xff08;三&#xff09;Adobe Audition cs6新增功能 一&#xff0c;Adobe Audition CS6 下载二&#xff0c;Adobe Audition C…

Adobe 中国

Adobe中国是Adobe公司在中国设立的分支机构&#xff0c;其总部位于上海。 Adobe中国的主要业务包括销售Adobe公司的软件产品、提供技术支持和服务、开展市场推广和宣传等工作。 作为全球领先的创意设计软件提供商&#xff0c;Adobe中国向中国用户提供了一系列功能强大的软件产…

数据仓库建设指导说明

文章目录 1、概念2、数仓特点3、数仓架构3.1、数据集市3.2、Inmon 架构3.3、Kimball 架构3.3.1、表分区3.3.1.1、事实表3.3.1.2、维度表3.3.1.2.1、维表设计步骤3.3.1.2.2、维度设计的建议3.3.1.2.3、主键设计3.3.1.2.4、缓慢变化维 SCD3.3.1.2.5、维表的整合与拆分3.3.1.2.5.1…

在CSDN的第1095天(3年),我收获了什么?

机缘 当初接触CSDN的时候是老师带进来的&#xff0c;那时候说人要有一个记录学习的习惯&#xff0c;可以记录很多东西&#xff0c;在后来看着老师的博客粉丝数和阅读数&#xff0c;哈哈哈&#xff0c;我心动了&#xff0c;于是就加了进来&#xff0c;记录点点滴滴。 于是开始…