BFS(广搜思想)


广度优先搜索

  • 广度优先搜索是图论的搜索算法之一,以下便进行简单叙述

对于每一个顶点来说,都存在着三种颜色

白色,灰色,黑色

而对于每个顶点,都有三种数据类型

颜色类型,前驱或者父节点,路程

分别用:color,u,d来表示



实现思想: BFS(G , s)
( G 为图,s 为初始点) struct node
{
collor ; //颜色,包含while, gray, black
d ; //距离
u ; //前驱或者父节点
}; 首先,把每一个顶点初始化,其中 u 初始化nullptr,d 初始化为 ∞ ,color 全部初始化为白色 然后把初始点( 起源点 )初始化为
s.color = Gray
s.d = 0
s.u = nullptr ;
然后,使用队列Q。首先初始化队列Q 使得队列Q为空
然后把 s 推进队列Q中, while(!Q.empty())//当队列非空
{
x = dequere(Q)//取出队头 ,然后让x为队列头,并且在队列中删除这一元素。 //然后在图中的每一个v , v是x的相邻节点进行循环
for( each v ∈ G.Adj[ x ] )//Adj是相邻点的意思
{
if( v.color == white )
{
v.color = gray//把点涂灰
v.d=x.d+1
v.u=x;
enqueue( Q, v )//把v放进刚刚的队列中
}
}
x.color= black//把点涂黑
}

下面是图示样例:

以下有部分差异信息

白色=白色 灰色=黄色 黑色=蓝色

  • 首先我们选择 ② 点开始,② 作为起源点,首先把 ② 点标记为黄色然后根据算法步骤,把 ② 点放进队列中,然后判断队列是否为空。此时不为空,那么就把队列的头弹出,并且寻找此结点对应的相邻结点。

  • 当找到相邻结点的时候,把相邻节点标记为黄色,把队列中弹出的头结点标记为蓝色。然后把对应的一结点和六结点标记成黄色,并且放进队列中。

  • 此时从队列中弹出 ① 结点,然后把 ① 结点标记成为蓝色,然后把 ① 结点标记为蓝色,把与 ① 结点相邻的结点标记为黄色,然后放进队列中

  • 同理,从队列中的头弹出一个元素,然后标记其相邻结点,再把其相邻结点涂成黄色,把其自身涂成蓝色,然后把相邻结点推进队列中,并且上一头元素

  • 依次弹出,③,⑦,然后依次把相邻结点推进队列中。然后分别标记③,⑦的相邻结点,然后继续进行下去

  • 到③被标记为蓝色的时候,去找③对应的相邻结点,找到了④,⑦。然而⑦已经在队列中了,说明⑦有其相对应的前驱结点,故不用标记⑦结点。由于⑦是在⑥标记的时候,与⑥的相邻结点,因此,⑦的前驱为⑥。此时,在队列中弹出的时候,其 d 值为其前驱结点中的 d 值加一而得。

随后,把⑦标记为蓝色,标记对应相邻结点,从而使前驱为该节点。然后进行类似上面的操作。

  • 直到所有的点都遍历完成,都标记为相对应的蓝色。此时队列为空。每一个点中都有从②号结点出发,到该结点的距离。


实现代码如下


#include<iostream>
#include<cstdlib>
#include<vector>
#include<string>
#include<queue>
using namespace std; struct Point
{
int dis=0;
string color="white";
Point* pre = nullptr;
}; void BFS(vector<vector<bool>>& if_arrive, vector<Point>&pos, int start, int n);
void Display_distance(vector<Point>& pos, int start); int main()
{
int n;
int a, b;
int start;
cout << "请输入有几个顶点" << endl;
cin >> n; vector<Point>pos(n);//点的位置以及前驱 //申请二维空间
vector <vector<bool>> if_arrive(n);
for (int i = 0; i < n; i++)
if_arrive[i].resize(n); cout << "请输入各个点之间的关系,(0,0)退出" << endl;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if_arrive[i][j] = false;
//初始化
while (cin >> a >> b && (a != 0 || b != 0))
if_arrive[a - 1][b - 1] = true; cout << "请输入开始点" << endl;
cin >> start; BFS(if_arrive, pos, start, n);//进行广搜 Display_distance(pos, start);//进行显示距离 //内存清理
for (int i = 0; i < n; i++)
if_arrive[i].clear();
if_arrive.clear();
pos.clear(); return 0;
} void BFS(vector<vector<bool>>& if_arrive, vector<Point>&pos, int start,int n)
{
int sit;
queue<int> Q;
start--;
pos[start].color = "black";//把源结点标记为黑色
pos[start].pre = nullptr;//源结点前驱为空
for (int i = 0; i < n; i++)
if (if_arrive[start][i] == true)//如果存在该路径
{
Q.push(i);//进队
pos[i].color = "gray";//相邻为灰色
pos[i].pre = &pos[start];
pos[i].dis++;
}
while (!Q.empty())//队列非空
{
sit = Q.front();//取头
Q.pop();//出队
for (int i = 0; i < n; i++)
{
if (if_arrive[sit][i] == true && pos[i].color == "white")
{
pos[i].color = "gray";//找到相邻的,先变颜色
pos[i].pre = &pos[sit];//然后前驱指向
pos[i].dis = pos[sit].dis+1;//然后距离加一
Q.push(i);//把i排进队列中
}
}
pos[sit].color = "black";//刚刚队列中的头的颜色标记为黑色
} } void Display_distance(vector<Point>&pos,int start)
{
vector<Point>::iterator iter;
int i = 1;
cout << "从第 " << start << " 点开始到各个点的距离" << endl;
for (iter = pos.begin(); iter < pos.end(); iter++, i++)
cout << "到第 " << i << " 个点的距离" << iter->dis << endl;
cout << endl;
}

程序运行结果如下


借鉴 《算法导论》 一书

BFS 简单思想以及代码的更多相关文章

  1. 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)

    深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...

  2. BFS简单题套路_Codevs 1215 迷宫

    BFS 简单题套路 1. 遇到迷宫之类的简单题,有什么行走方向的,先写下面的 声明 ; struct Status { int r, c; Status(, ) : r(r), c(c) {} // ...

  3. 深度优先搜索DFS和广度优先搜索BFS简单解析

    转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...

  4. AcWing:176. 装满的油箱(bfs + dijiskla思想)

    有N个城市(编号0.1…N-1)和M条道路,构成一张无向图. 在每个城市里边都有一个加油站,不同的加油站的单位油价不一样. 现在你需要回答不超过100个问题,在每个问题中,请计算出一架油箱容量为C的车 ...

  5. HTML QQ聊天代码 简单的一行代码

    简单的一行代码: <a href="tencent://message/?uin=173007740&Site=&Menu=yes">和17300774 ...

  6. qt简单界面更新代码(菜鸟级)(部分代码)

    qt简单界面更新代码(菜鸟级)(部分代码)self.timers_1=QtCore.QTimer(self)self.timers_1.timeout.connect(self.min_1)self. ...

  7. Spring源码学习:第1步--在Spring源码中添加最简单的Demo代码

    为了最大程度地贴近Spring源码并进行学习,一种比较直接的做法是:直接在Spring源码中加入Demo代码,并进行调试. 参照以前使用Spring的经验,Spring最简单的使用方法是:一个实体类. ...

  8. JS实现简单的运行代码 & 侧边广告

    /* JS实现简单的运行代码功能 */<!doctype html> <html> <head> <meta charset="utf-8" ...

  9. 简单的jQ代码

    简单的jQ代码 /* * Lazy Load - jQuery plugin for lazy loading images * * Copyright (c) 2007-2012 Mika Tuup ...

随机推荐

  1. ZOJ 3512 Financial Fraud (左偏树)

    题意:给定一个序列,求另一个不递减序列,使得Abs(bi - ai) 和最小. 析:首先是在每个相同的区间中,中位数是最优的,然后由于要合并,和维护中位数,所以我们选用左偏树来维护,当然也可以用划分树 ...

  2. iOS横屏设置的几种方式

    1.界面旋转,MainScreen的宽高不变,键盘位置不变 CGFloat duration = [UIApplication sharedApplication].statusBarOrientat ...

  3. zookeeper原理与实践(一)----zookeeper的基本功能

    我们现在围绕两个问题来学习zookeeper: 什么是zookeeper? zookeeper基础知识 什么是zookeeper: zookeeper是hadoop下面的一个子项目,是一个分布式协调服 ...

  4. 交叉编译调试qemu_guest_agent

    Winodws版本 编译环境Fedora23 下载VSS SDK的setup.exe 下载地址 提取VSS SDK头文件 将下面的代码保存成extract-vsssdk-headers.sh脚本,然后 ...

  5. [UE4]如何替换角色Mesh上的Material材质

    http://www.dawnarc.com/2016/10/ue4%E5%A6%82%E4%BD%95%E6%9B%BF%E6%8D%A2%E8%A7%92%E8%89%B2mesh%E4%B8%8 ...

  6. uoj#388. 【UNR #3】配对树(线段树合并)

    传送门 先考虑一个贪心,对于一条边来说,如果当前这个序列中在它的子树中的元素个数为奇数个,那么这条边就会被一组匹配经过,否则就不会 考虑反证法,如果在这条边两边的元素个数都是偶数,那么至少有两组匹配经 ...

  7. 剑指Offer的学习笔记(C#篇)-- 从尾到头打印链表

    题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 一 . 个人想法 这个题目搞了一段时间,因为解法好多,比如:是用递归法呢还是循环呢,要不要使用栈呢等等.. 所以,每一种想法 ...

  8. B-Tree深入理解

    定义: 根节点至少包括两个孩子 树中每个节点最多含有m个孩子(m>=2) 除根节点和叶子节点外,其他每个节点字少有(ceil(m/2):去上线),个孩子. 所有叶子节点都位于同一高度 假设每个非 ...

  9. P1295-创意吃鱼

    题目描述 回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*).她发现,把大池子视为01矩阵(0表示对应位置无鱼,1 ...

  10. mac for Idea配置Tomcat

    参考链接地址:http://blog.csdn.net/zsy3313422/article/details/52583091 IntelliJ使用 ##使用IntelliJ IDEA配置web项目时 ...