广度优先搜索(BFS)

自己对于广度优先搜索的理解:
与深度优先搜索(DFS)相对应,广度优先搜索是指,立足于当前的某一个节点,每一次将遍历所有离该节点最近的节点(也就是距离为1的节点),然后再将这些刚刚被当作最近节点遍历的节点全部依次作为当前节点进行下一次对所有最近节点的遍历,依次类推,直到找到想要的节点和路径。
从我自己的算法描述可以看出,广度优先搜索是一种顾名思义的算法,类似于层序遍历,即每一次的搜索都将达到最广的范围,也就是每次都将触手可及的所有节点都找到,就像展开一颗一层一层排列的树一样。
为了更加形象地表示广度优先搜索的过程,我们可以从上面这张图来阐述一次广度优先搜索的过程。
加入我们将v3节点作为搜索的起始节点s,那么从s出发,我们第一次搜索先遍历那些距离s为1的所有节点,我们可以找到这样的节点有v1,v6。本轮搜索结束,然后我们再依次将刚才找到的v1,v6节点为当前节点,寻找距离当前节点为1的节点,所以我们又找到了v2,v4.这里需要注意的是虽然有节点和v6节点只一边之遥,但是根据图的有向性,从v6节点并不能到达这些节点,所以我们并没有从v6节点找到别的节点。又一次,我们从v2,v4节点找到了v5,v7节点,这里v3已经被找到过了,不应当走遍历重复节点,所以到此所有可遍历的节点都被遍历了,广度优先搜索结束。

广度优先搜索的代码实现

我们可以利用一个队列来实现上面所述的算法,先将当前节点入队,然后再遍历每一个当前节点将可以从当前节点达到的距离为1的所有节点入队,然后将当前节点出队,依次类推,这样利用队列将当前节点从队首出队,再将相邻节点从队尾入队的方式可以保证所有下一节点都在所有当前节点全部被处理完成后再进行处理。

#include <stdio.h>
#include <stdlib.h>
#define INIT_SIZE 50
//利用二维数组定义邻接表
static map[8][8]={0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0
} ;//map[i][j]=1表示可以从节点i到达节点j //定义一个循环队列以实现算法typedef struct Queue{int front;int rear;int elements[INIT_SIZE];}Queue;void Init_Queue(Queue *q) {q->front=q->rear=0;}
void InQueue(int element,Queue *q) //入队
{q->elements[q->rear++]=element;q->rear=(q->rear)%INIT_SIZE;}
int DeQueue(Queue *q)//出队
{int element=q->elements[q->front++];q->front=(q->front)%INIT_SIZE;return element;
}int Empty(Queue *q){if(q->rear==q->front){return 1;}else return 0;}int BFS(int start,int end)//BFS算法从start位置到end位置寻找最短路径 {int last=start,flag=0;Queue q;int i,j,t,step=0;Init_Queue(&q);InQueue(start,&q);while(!Empty(&q)){    t=DeQueue(&q);if(t==last) {flag=1;step++;}for(j=1;j<=7;j++){if(map[t][j]==1&&j!=start){if(j==end) return ++step;if(flag==1) last=j;InQueue(j,&q);}} flag=0;}return step;}main(){int step,start=3,end=7;step=BFS(start,end);printf("从%d节点到%d节点的最短距离为:%d\n",start,end,step);}

对上面的代码,进行一些补充解释:
算法思路上面已经大致说明,主要就是通过队列出队入队的逻辑实现类似层序遍历的操作。
而为了记录遍历的层数,也就是当前节点到起始节点s间的距离,我们这里使用了两个变量来实现来实现了这一功能:
其中last变量表示记录当前层的最后一个节点,其实第一层只有s节点一个,所以我们将last默认赋值为起始节点s,然后在每当last节点要遍历临近节点时,我们需要在这个过程中不断更新last的值,因为只有last节点遍历的最后一个节点才是下一层的最后一个节点。
那么具体到算法实现上的操作就是判断如果出队的节点是上一次被标记的last节点,那么意味这这一层的最后一个节点已经被处理完了,那么就给步数step加1,然后通过一个标志flag来打开一个开关以更新last的值,因为在last节点被出队时,意味着下一层的节点也即将被查找完毕,此时我们需要不断更新last节点查找到的值来作为下一层的新last节点。

      t=DeQueue(&q);if(t==last)//判断是否到达last节点 {flag=1;//通过flag打开更新last节点的开关step++;//本层处理完毕,步数加1}for(j=1;j<=7;j++){if(map[t][j]==1&&j!=start){if(j==end) return ++step;if(flag==1) last=j;//如果开关被打开,那么查找的同时更新last的值InQueue(j,&q);}}

这样我们就可以随时记录遍历的层数或者是走的步数了。

路径的记录

上面的代码虽然可以确保遍历所有节点和路径,并找到最少的步数,但是仍然无法获取最短路径的记录,即便我们确实在不经意间遍历了最短路径,但是我们仍需要开辟额外的空间取记录最短路径。
要确保路径是最短的,那么就要确保这条路径上的每一个节点的上一个节点在所有可以达到本节点的节点中具有最浅的深度,相对于起始节点而言。所以为了记录最短的路径,我们不但需要开辟一个记录最短路径的空间,还需要开辟一个记录节点深度的空间。
为此,我们再专门定义两个数组,我将它们分别称为depath和minpath,其中depath数组的每一个元素对应每一个节点的深度,也就是从s节点出发到达这一节点的最小距离,而minpath用来记录可以到达该节点的所有节点中深度最小的一个。
例如v1和v2都可以到达v4,但是v1的深度为1,v2的深度为2,所以我们记录可以到达v4的最浅临近节点minpath[4]=1.
我们在全局声明这样的两个数组,然后对BFS算法做以下更改:

int depath[8]={-1,-1,-1,-1,-1,-1,-1,-1} ;
int minpath[8]={-1,-1,-1,-1,-1,-1,-1,-1} ;

更改后的BFS算法:

int BFS(int start,int end)//BFS算法从start位置到end位置寻找最短路径 {int last=start,flag=0;Queue q;int i,j,t,step=0;Init_Queue(&q);InQueue(start,&q);while(!Empty(&q)){ t=DeQueue(&q);if(depath[t]==-1)//如果某一节点的depath值为1,说明该节点还没有被赋予深度{depath[t]=step;//那么将当前搜索的层数赋值给该节点的深度值}if(t==last) {flag=1;step++;}for(j=1;j<=7;j++){if(map[t][j]==1&&j!=start){if(flag==1) last=j;if(j==end){minpath[j]=minpath[j]==-1?(t):(depath[minpath[j]]>depath[t]?t:minpath[j]);return ++step;}InQueue(j,&q);//更新可以到达该处的最近节点minpath[j]=minpath[j]==-1?(t):(depath[minpath[j]]>depath[t]?t:minpath[j]);}} flag=0;}return step;}

关键的更改代码在于:

if(depath[t]==-1)//如果某一节点的depath值为1,说明该节点还没有被赋予深度{depath[t]=step;//那么将当前搜索的层数赋值给该节点的深度值}
minpath[j]=minpath[j]==-1?(t):(depath[minpath[j]]>depath[t]?t:minpath[j]);

第一处代码意在给第一次被探索到的新节点赋于其最小深度,因为第一次被探索时该节点可以得到的深度一定是最小的。
第二处的代码用来获取或更新可以到达节点j的最小深度的临近节点。
如果minpath[j]的值为-1,说明还没有临近节点探索到它,那么就将t作为这样的第一个节点。如果值不等于1,那么说明已经有minpath[j]这样一个节点发现了它,所以我们将t的深度和minpath[j]节点的深度进行比较,将minpath[j]更新为它们当中深度最小的那一个。

如此以来,当广度优先搜索完成后,我们将得到每一个节点的深度和可到达它们的最浅临近节点,而后者的意义在于,我们可以通过一直追溯这样的最浅节点来得到一条最小的路径。其获得路径的简单代码如下:

 i=end;while(minpath[i]!=start){printf("%d->",minpath[i]);i=minpath[i];}printf("%d",start);

这样可以通过遍历minpath数组获得一条从终点到起点的最短路径,而我们只要通过一个栈的逻辑就可以将它转换为从起点到终点的一条最小路径,这样的实现是非常简单的。

以最开始我们给出的那个有向图为例,我们通过给粗的BFS得出如下结果:

图论——广度优先搜索相关推荐

  1. a - 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历_数据结构--图

    故事凌 今天 基本知识点 图可说是所有数据结构里面知识点最丰富的一个, 自己笨的知识点如下: 阶(oRDER), 度: 出度(out-Degree), 入度(in-Degree) 树(Tree), 森 ...

  2. SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...

  3. SDUT 2142 数据结构实验之图论二:基于邻接表的广度优先搜索遍历

    数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Descript ...

  4. 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历(BFS)

    Description 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) Input 输入第一行为 ...

  5. 数据结构实验之图论二:基于邻接表的广度优先搜索遍历

    题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) 输入 输入第一行为整数n(0< ...

  6. 6.1 图的深度优先和广度优先搜索

    图的广度优先搜索 图的的搜索算法主要分为广度优先搜索(breadth-first search或BFS)和深度优先搜索(depth-first search或DFS).首先讨论广度优先搜索算法. 称之 ...

  7. 图的遍历——深度优先搜索+广度优先搜索

    一:图的遍历--深度优先搜索 在本文其他内容中只是大体概括了主要的图论内容,更加详细的代码实现及算法分析在此给出. 深度优先搜索(DFS)类似树的先序遍历. 假设初始状态是图中所有顶点未曾被访问,则深 ...

  8. 广度优先搜索解决欧拉回路时间复杂度_迷宫搜索类的双向bfs问题(例题详解)

    前言 文章若有疏忽还请指正! 更多精彩还请关注公众号:bigsai 头条号:一直码农一直爽 在搜索问题中,以迷宫问题最具有代表性,无论是八皇后的回溯问题,还是dfs找出口,bfs找最短次数等等题目的问 ...

  9. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS)

    广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS) 1. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first searc ...

最新文章

  1. Redhat下XFS的安装
  2. 分析:“AI on Hadoop”有意义吗?
  3. Python网络编程中的select 和 poll I/O复用的简单使用
  4. flume + kafka
  5. pda连接电脑无法存取文件_手机无法连接电脑怎办
  6. Python机器学习及实践+从零开始通往Kaggle竞赛之路
  7. vue-Resource(与后端数据交互)
  8. 如何设置固定宽度 td ?
  9. nginx websocket 代理
  10. 微软Win11 商店各个应用可单独下载
  11. mysql代码创建表博客园_数据库——用代码创建表
  12. 华为外包公司一面二面三面回顾
  13. 游吟诗人之中二病犯了
  14. Java Web 网络商城案例演示一、(环境搭建)
  15. 看,2021年,一个普通应届生的成长之旅
  16. 评论-Mophie果汁包(不是果汁包空气)
  17. 免费合同管理软件有哪个好用?有哪些功能?
  18. 利用MapInfo软件实现TAB格式到MIF格式的转换
  19. 粒子特效遮罩 UGUI SpriteMask
  20. 计算机网络学习笔记第一章(概述) 超详细整理

热门文章

  1. IDEA如何多次启动同一个程序
  2. CSS3 transform变形属性、2D变形、3D变形
  3. mysql 1代表true(MySQL数据类型详解)
  4. HTML5 weui笔记
  5. 2015网易游戏校园招聘笔试题 研发岗
  6. Python-pydicom读取dcm文件报错-2021.6.5
  7. 《嵌入式 - STM32开发指南》手把手教你搭建STM32开发环境 [Windows版 - 1]
  8. python分布式计算框架_基于Python的分布式计算平台-DPark
  9. NLP之基于TextCNN的文本情感分类
  10. JBOSS EAP 6 系列七 JPA/hibernate