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

【数据结构】图的遍历:广度优先(BFS),深度优先(DFS)

目录

1、广度优先(BFS)

算法思想 

广度优先生成树 

知识树 

代码实现 

2、深度优先(DFS)

算法思想 

深度优先生成树

知识树 

代码实现 


1、广度优先(BFS)

算法思想 

         图的广度优先遍历(BFS)是一种遍历图的算法,其思想是从起始顶点开始遍历图,先访问起始顶点的所有直接邻居,然后遍历这些邻居的直接邻居,以此类推,直到遍历完整个图。

BFS算法需要使用一个队列来保存已经遍历过但还未访问其邻接顶点。具体步骤如下:

  1. 将起始顶点加入队列中,并标记为已访问。
  2. 从队列中取出一个顶点V,并依次访问V的所有未被访问的邻接顶点,并将这些邻接顶点加入队列中,并标记为已访问。
  3. 重复步骤2,直到队列为空。

广度优先生成树 

         广度优先搜索(BFS)可以用来生成一棵图的广度优先生成树(BFS树),该树的根节点为起始节点,其余节点按照宽度优先的顺序依次加入。BFS树可以用来解决最短路径问题,以及其他需要按照距离或层次访问节点的问题。

具体的实现步骤如下:

  1. 初始化BFS树,将起始节点加入树中。
  2. 将起始节点加入待访问队列。
  3. 对于队列中的每个节点,依次遍历其所有邻居节点。
  4. 对于每个邻居节点,如果该节点还未加入BFS树,则将其加入,并将该邻居节点的父节点设为当前节点。
  5. 将已访问的节点从队列中移除。
  6. 重复步骤3-5,直到队列为空。

知识树 

 

代码实现 

 下面是C语言实现BFS的示例代码:

#include <stdio.h>
#include <stdlib.h>#define MAXV 100  // 最大顶点数typedef struct {int edges[MAXV][MAXV];  // 邻接矩阵int n;  // 顶点数
} Graph;typedef struct {int data[MAXV];int front, rear;
} Queue;int visited[MAXV];  // 标记已经遍历的结点void initQueue(Queue* q) {q->front = q->rear = 0;
}void enqueue(Queue* q, int x) {q->data[q->rear++] = x;
}int dequeue(Queue* q) {return q->data[q->front++];
}int isEmpty(Queue* q) {return q->front == q->rear;
}void initGraph(Graph* g, int n) {g->n = n;for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)g->edges[i][j] = 0;
}void addEdge(Graph* g, int u, int v) {g->edges[u][v] = 1;g->edges[v][u] = 1;
}void bfs(Graph* g, int u) {Queue* q = (Queue*) malloc(sizeof(Queue));initQueue(q);visited[u] = 1;printf("%d ", u);enqueue(q, u);while (!isEmpty(q)) {int v = dequeue(q);for (int w = 0; w < g->n; w++) {if (g->edges[v][w] && !visited[w]) {visited[w] = 1;printf("%d ", w);enqueue(q, w);}}}
}int main() {Graph g;int n, m, u, v;printf("输入顶点数和边数:");scanf("%d %d", &n, &m);initGraph(&g, n);printf("输入每条边的两个端点:\n");for (int i = 0; i < m; i++) {scanf("%d %d", &u, &v);addEdge(&g, u, v);}printf("输入起始顶点:");scanf("%d", &u);printf("广度优先遍历结果:");bfs(&g, u);printf("\n");return 0;
}

        首先定义了一个邻接矩阵表示图,以及一个队列来存放待遍历的顶点。初始化队列为空,然后将起始顶点加入队列,并标记为已访问。然后开始遍历队列中的顶点,对于每个顶点,遍历其未访问的邻居,将其添加到队列中,并标记为已访问。代码中使用了visited数组来标记顶点是否已经被访问过了。

在以上代码中,输入格式为:

5 6
0 1
0 2
1 2
2 3
1 3
3 4
0

其中第一行为总顶点数和总边数,第2~m+1行为每条边的两个端点,然后输入起始顶点编号。

2、深度优先(DFS)

算法思想 

        图的深度优先遍历(Depth-First Search,DFS)是一种遍历图的算法。其基本思想是从一个顶点开始,沿着一条路径一直走到底,直到所有的路径都被探索过为止。如果还有顶点未被访问,则回溯到前一个顶点,继续搜索下一条路径,直到所有的顶点都被访问为止。

具体实现过程如下:
1. 从某一顶点开始遍历,将该顶点标记为已访问。
2. 对当前访问的顶点的所有未访问的邻接顶点进行访问,即从当前顶点的邻接顶点开始深度优先遍历。
3. 重复步骤2,直到所有的顶点都被访问。

        图的深度优先遍历可以用递归或栈来实现。在递归实现中,每次访问一个顶点时,递归地访问其未访问的邻接顶点,直到所有的顶点都被访问。在栈实现中,首先将起始顶点入栈,然后对栈内的顶点进行出栈、访问、入栈操作,直到所有的顶点都被访问。

深度优先生成树

        深度优先生成树(depth first search tree)是一棵以图中某个顶点为根的深度优先遍历树,它的生成过程为:

  1. 选择图中任意一个未被遍历的顶点作为根节点;
  2. 以根节点为起点进行深度优先遍历;
  3. 遍历到一个未被遍历的节点时,将该节点加入到生成树中,并将其父节点与该节点之间的边添加到生成树中;
  4. 如果图中还存在未被遍历的节点,则在剩余未被遍历的节点中选择一个节点作为新的根节点,并重复上述过程。

        生成树的过程可以通过递归实现,也可以使用栈来实现。在遍历的过程中,需要记录每个节点的状态,即已被发现、已被访问或未被发现。

知识树 

 

代码实现 

 以下是C语言中实现图的深度优先遍历的代码:

#include <stdio.h>
#include <stdbool.h>#define MAX_VERTEX_NUM 100  // 顶点最大数量typedef struct {int vertex;  // 顶点int next;    // 指向下一个邻接点的指针
} EdgeNode;typedef struct {int vertex;      // 顶点EdgeNode *edge;  // 指向邻接点链表的指针
} VertexNode;VertexNode graph[MAX_VERTEX_NUM];  // 图
bool visited[MAX_VERTEX_NUM];      // 记录哪些顶点已经被访问过void addEdge(int v1, int v2) {// 添加边(v1, v2)EdgeNode *edge = graph[v1].edge;if (edge == NULL) {graph[v1].edge = (EdgeNode *) malloc(sizeof(EdgeNode));graph[v1].edge->vertex = v2;graph[v1].edge->next = -1;} else {while (edge->next != -1) {edge = graph[v1].edge + edge->next;}edge->next = graph[v1].edge - edge + addEdge(v2, -1);}
}void dfs(int vertex) {visited[vertex] = true;printf("%d ", vertex);EdgeNode *edge = graph[vertex].edge;while (edge != NULL) {int nextVertex = edge->vertex;if (!visited[nextVertex]) {dfs(nextVertex);}edge = graph[vertex].edge + edge->next;}
}int main() {int n, m;scanf("%d %d", &n, &m);  // n表示顶点数,m表示边数for (int i = 1; i <= n; i++) {graph[i].vertex = i;}for (int i = 0; i < m; i++) {int v1, v2;scanf("%d %d", &v1, &v2);addEdge(v1, v2);addEdge(v2, v1);  // 在无向图中,边(v1, v2)和边(v2, v1)都要添加}memset(visited, false, MAX_VERTEX_NUM);  // 初始化visited数组printf("DFS: ");dfs(1);  // 从顶点1开始进行DFSreturn 0;
}

        其中addEdge函数用于添加一条边。在main函数中,先读入图的顶点数和边数,然后依次读入每条边,并调用addEdge函数添加边。最后,初始化visited数组为false,并从顶点1开始进行深度优先遍历。

相关文章:

【数据结构】图的遍历:广度优先(BFS),深度优先(DFS)

目录 1、广度优先&#xff08;BFS&#xff09; 算法思想 广度优先生成树 知识树 代码实现 2、深度优先&#xff08;DFS&#xff09; 算法思想 深度优先生成树 知识树 代码实现 1、广度优先&#xff08;BFS&#xff09; 算法思想 图的广度优先遍历&#xff0…...

Mysql 学习总结(89)—— Mysql 库表容量统计

前言 统计每个库每个表的大小是数据治理中最简单的一个要求,下面从抽样统计结果及精确统计结果两方面来统计MySQL的每个库每个表的数据量情况。mysql 数据字典库 information_schema 里记录了统计的预估数据量(innodb 引擎表不准确,MyISAM 引擎表准确)及数据大小、索引大小及…...

virtualBox安装配置使用

virtualBox下载 //官网下载地址 https://www.virtualbox.org/wiki/Downloads ​ //ubuntu下载地址 https://cn.ubuntu.com/download/server/step1 virtualBox使用 导入现有镜像 &#xff08;如果报错可以降低系统配置&#xff0c;因为有些主机可能不支持高配置&#xff0c;例如…...

北斗导航 | RTD、RTK完好性之B值、VPL与HPL计算(附B值计算matlab源代码)

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 1、S矩阵获取 为第i颗卫星测距标准差:...

more often than not 的含义

今天听https://www.bilibili.com/video/BV1w94y12727/?p2&spm_id_frompageDriver more often than not 连读:mor ofen than au 想了半天不动什么意思. 查了一下表示大部分情况下. 还是不理解为什么, 就查了必应里面的词典. 表示超过一半的情况下. 又自己想了想突然懂了.…...

【Linux】Linux环境配置安装

目录 一、双系统&#xff08;特别不推荐&#xff09; 安装双系统的缺点&#xff1a; 安装双系统优点&#xff08;仅限老手&#xff09;&#xff1a; 二、虚拟机centos7镜像&#xff08;较为推荐推荐&#xff09; 虚拟机的优点&#xff1a; 虚拟机的缺点&#xff1a; ​ …...

从零学习开发一个RISC-V操作系统(二)丨GCC编译器和ELF格式

本篇文章的内容 一、GCC&#xff08;GUN Compiler Collection&#xff09;1.1 GCC的命令格式1.2 GCC的主要执行步骤1.3 GCC涉及的文件类型 二、ELF简介2.1 ELF文件格式图2.2 ELF文件处理的相关工具2.3 练习 本系列是博主参考B站课程学习开发一个RISC-V的操作系统的学习笔记&…...

论文阅读_大语言模型_Llama2

英文名称: Llama 2: Open Foundation and Fine-Tuned Chat Models 中文名称: Llama 2&#xff1a;开源的基础模型和微调的聊天模型 文章: http://arxiv.org/abs/2307.09288 代码: https://github.com/facebookresearch/llama 作者: Hugo Touvron 日期: 2023-07-19 引用次数: 11…...

当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用及论文写作、拓展分析

生态系统服务是人类从自然界中获得的直接或间接惠益&#xff0c;可分为供给服务、文化服务、调节服务和支持服务4类&#xff0c;对提升人类福祉具有重大意义&#xff0c;且被视为连接社会与生态系统的桥梁。自从启动千年生态系统评估项目&#xff08;Millennium Ecosystem Asse…...

k8s Limits 限制内存

Limits 限制内存 在 Kubernetes (K8s) 中&#xff0c;可以使用 Limits&#xff08;资源限制&#xff09;来限制 Pod&#xff08;容器&#xff09;使用的内存数量。此处的 Limits 表示 Pod 在 K8s 集群中可用的最大内存量。一旦 Pod 内存使用超过这个限制&#xff0c;可能会触发…...

单片机第三季-第三课:STM32开发板原理图、配置、浮点运算单元

目录 1&#xff0c;开发板原理图 2&#xff0c;浮点运算单元&#xff08;FPU&#xff09; 1&#xff0c;开发板原理图 课程视频比较早&#xff0c;介绍了三款开发板。观看视频时用的开发板说和51单片机共板的STM32核心板&#xff0c;将51单片机从底座拆下来后&#xff0c;安…...

观察者模式 发布-订阅模式(设计模式与开发实践 P8)

文章目录 观察者模式运用实现 观察者模式 定义&#xff1a;他用来定义对象之间一种一对多的依赖关系&#xff0c;当一个对象状态发生改变时&#xff0c;所有依赖他的对象都会得到通知 运用 如果我们使用过 DOM 上的事件函数&#xff0c;那就接触过观察者模式 document.body…...

【日常业务开发】Java实现异步编程

【日常业务开发】Java实现异步编程 Java实现异步编程什么是异步异步的八种实现方式异步编程线程异步Future异步CompletableFuture实现异步Spring的Async异步Spring ApplicationEvent事件实现异步消息队列ThreadUtil异步工具类Guava异步 CompletableFuture异步编排工具类创建异步…...

学习笔记|模数转换器|ADC原理|STC32G单片机视频开发教程(冲哥)|第十七集:ADC采集

文章目录 1.模数转换器&#xff08;ADC&#xff09;是什么&#xff1f;手册说明&#xff1a; 2.STC32G单片机ADC使用原理19.1.1 ADC控制寄存器&#xff08;ADC_CONTR)19.1.2 ADC配置寄存器&#xff08;ADCCFG)19.1.4ADC时序控制寄存器&#xff08;ADCTIM&#xff09;19.3 ADC相…...

OpenCV实现“蓝线挑战“特效

原理 算法原理可以分为三个流程&#xff1a; 1、将视频&#xff08;图像&#xff09;从&#xff08;顶->底&#xff09;或&#xff08;左->右&#xff09;逐行&#xff08;列&#xff09;扫描图像。 2、将扫描完成的行&#xff08;列&#xff09;像素重新生成定格图像…...

容器管理工具 Docker生态架构及部署

目录 一、Docker生态架构 1.1 Docker Containers Are Everywhere 1.2 生态架构 1.2.1 Docker Host 1.2.2 Docker daemon 1.2.3 Registry 1.2.4 Docker client 1.2.5 Image 1.2.6 Container 1.2.7 Docker Dashboard 1.3 Docker版本 二、Docker部署 2.1 使用YUM源部署…...

js判断数据类型的方法

简单数据类型用&#xff1a;typeof&#xff0c; // 可以直接typeof空格接数据的方式,也可以typeof(数据)的方式使用 console.log(typeof ""); //string(检验字符串没问题) console.log(typeof 1); //number(检验数字没问题) console.log(typ…...

达梦数据库随系统开机自动启动脚本

写一个脚本&#xff0c;实现在服务器开机后自动启动达梦数据库的功能。 1. 在/etc/init.d/目录下&#xff0c;编写脚本&#xff0c;并将脚本命名为startdm.sh。脚本内容实现如下&#xff1a; #!/bin/bash #chkconfig:2345 80 90 #decription:启动达梦# 切换到 dmdba 用户 su …...

Python开发利器之VS Code

Python官方提供了一个Python集成开发环境&#xff08;IDE&#xff09;&#xff1a; IDLE (Integrated Development and Learning Environment)。 它提供了一个图形用户界面&#xff0c;可以让开发者编写、调试和执行Python程序。IDLE包含Python解释器、代码编辑器、调试器和文件…...

【Axure视频教程】输入框控制滑动评分条

今天教大家在Axure里如何制作输入框控制滑动评分条的原型模板&#xff0c;可以通过鼠标左右拖动滑块&#xff0c;也可以点击条形让滑块移动到指定位置&#xff0c;标签和输入框里会返回具体的分值&#xff0c;分值由滑块所在的位置动态计算而成&#xff1b;也可以在输入框里输入…...

【学习笔记】[AGC064C] Erase and Divide Game

有点难&#x1f605;&#xff0c;看到比自己低一级的选手场切这道题就更绷不住了&#x1f607; 考虑 从低到高位 建立 trie \text{trie} trie 树&#xff0c;但是因为是对反串建立的&#xff0c;所以编号连续的点在 trie \text{trie} trie 树上的位置是分散的&#x1f605; …...

算法通关村-----数组中元素出现次数问题

数组中出现次数超过一半的数字 问题描述 数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个数字。你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。详见剑指offer39 问题分析 最直接的方式就是使用hashMap,遍历给定数组&#xff0c…...

Qt-键盘消息的传递-键盘消息的获取-C++

文章目录 1.概述2.焦点3.强制获取键盘消息4.键盘常用组合方法5.总结 1.概述 QKeyEvent 类用来描述一个键盘事件。当键盘按键被按下或者被释放时&#xff0c;键盘事件便会被发送给拥有键盘输人焦点的部件。 QKeyEvent 的 key() 函数可以获取具体的按键&#xff0c;对于 Qt 中给…...

数据结构与算法(五)--链表概念以及向链表添加元素

一、前言 今天我们学习另一种非常重要的线性数据结构–链表&#xff0c;之前我们已经学习了三种线性数据结构&#xff0c;分别是动态数组&#xff0c;栈和队列。其中队列我们额外学习了队列的另一种实现方式–循环队列。其实我们自己实现过前三个数据结构就知道&#xff0c;它…...

计算机视觉与深度学习-图像分割-视觉识别任务02-目标检测-【北邮鲁鹏】

目录标题 参考目标检测定义深度学习对目标检测的作用单目标检测多任务框架多任务损失预训练模型姿态估计 多目标检测问题滑动窗口&#xff08;Sliding Window&#xff09;滑动窗口缺点 AdaBoost&#xff08;Adaptive Boosting&#xff09;参考 区域建议 selective search 思想慢…...

Flink——Flink检查点(checkpoint)、保存点(savepoint)的区别与联系

Flink checkpoint Checkpoint是Flink实现容错机制最核心的功能&#xff0c;能够根据配置周期性地基于Stream中各个Operator的状态来生成Snapshot&#xff0c;从而将这些状态数据定期持久化存储下来&#xff0c;从而将这些状态数据定期持久化存储下来&#xff0c;当Flink程序一…...

[篇五章五]-如何禁用 Windows Defender-我的创作纪念日

################################################## 目录 禁用掉烦人的 Windows Defender 在本地组策略编辑器中禁用 Windows Defende 关闭 Microsoft Defender 防病毒 禁止 Defender 开机自动运行 重新激活 Windows Defender #######################################…...

什么情况下使用微服务?

单体架构图参考网络&#xff1a; 1. 什么是单体应用 单体应用就是将应用程序的所有功能都打包成一个独立的单元&#xff0c;最终以一个WAR包或JAR包存在&#xff0c;没有外部的任何依赖&#xff0c;里面包含DAO、Service、UI等所有的逻辑。 优点&#xff1a; &#xff11;&…...

【Linux】Ubuntu美化主题【教程】

【Linux】Ubuntu美化主题【教程】 文章目录 【Linux】Ubuntu美化主题【教程】1. 安装优化工具Tweak2.下载自己喜欢的主题3. 下载自己喜欢的iconReference 1. 安装优化工具Tweak 首先安装优化工具Tweak sudo apt-get install gnome-tweak-tool安装完毕后在菜单中打开Tweak 然后…...

spring-boot2.x,使用EnableWebMvc注解导致的自定义HttpMessageConverters不可用

在json对象转换方面&#xff0c;springboot默认使用的是MappingJackson2HttpMessageConverter。常规需求&#xff0c;在工程中使用阿里的FastJson作为json对象的转换器。 FastJson SerializerFeatures WriteNullListAsEmpty &#xff1a;List字段如果为null,输出为[],而非nu…...

注销主体和注销网站/seowhy培训

虽然平时能利用插件来实现&#xff0c;但是总是觉得&#xff0c;如果连个无缝轮播都写不出来&#xff0c;还玩个毛线&#xff1b; 其实现在还真的是玩毛线&#xff0c;因为代码都是别人的&#xff0c;不过嘛&#xff0c;很快就变成是我的啦&#xff01; 代码还没封装成插件&…...

黑龙江省机场建设集团官网网站/软文客

前言: 搞java开发的时候突然对网络产生了兴趣,兜兜转转最终还是再次学习起了大二时候经常不听课自学的网络原理. 参考视频是慕课网上的 一站式学习Java网络编程 全面理解BIO/NIO/AIO 第二章 与 剑指Java面试-Offer直通车 第二章. 目录 第一章 网络基础知识 1.1 七层网络协议…...

做网站怎么买断源码/如何快速推广

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼看下 GtkEntry 的源码不就知道了。。。gtk_entry_get_display_text...if (end_pos < start_pos)return g_strdup ("");else if (priv->visible){start g_utf8_offset_to_pointer (text, start_pos);end g_utf8_o…...

上网站建设公司/百度云搜索引擎官网入口

有时根据题意需得根据输入的二维数来动态的创建二维数组&#xff0c;那么此时就不能想以前一样直接定义多少行多少列了。因为不知道行列多少&#xff0c;假如设定太大浪费空间&#xff0c;申请太小完成不了程序的数据存储。因此需要合理的开辟二维空间。以下的两种方法都可以建…...

有什么网站可以下做闭软件/市场营销策划案的范文

目的&#xff1a;从指定的身份证号码中提取出去年月。 方法&#xff1a; 1、选定目标单元格。 2、输入公式&#xff1a;TEXT(MID(C3,7,8),"00-00-00")。 3、CtrlEnter填充。 解读&#xff1a; 1、利用MID函数从C3单元格中提取从第7个开始&#xff0c;长度为8的字符串…...

网站策划案怎么做/做百度推广的公司电话号码

MySQL Hash索引和B-Tree索引的区别究竟在哪里呢&#xff1f;相信很多人都有这样的疑问&#xff0c;下文对两者的区别进行了详细的分析&#xff0c;供您参考。 Mysql Hash索引结构的特殊性&#xff0c;其检索效率非常高&#xff0c;索引的检索可以一次定位&#xff0c;不像B-T…...