DFS&&BFS
DFS
DFS搜索是按照深度的方向搜索,它类似于树的先根遍历,是树的先根遍历的推广。
1.从图的某个顶点v0出发,首先访问v0,
2.找出刚访问过的顶点的第一个未被访问过的邻接点,然后访问该结点,以该结点为新顶点,重复,直到刚访问过的结点没有未被访问过得邻接点为止。
3.返回前一个访问过得且仍有未被访问的邻接点的顶点,找出该结点的下一个未被访问的邻接点,访问该顶点,执行步骤2
下面是邻接矩阵和邻接表存储时DFS访问的代码
#include <iostream>
#include <queue>
#define INF 0x3f3f
using namespace std;
/***************图用邻接矩阵表示***************/
class Graph_a
{
private:
int num;//顶点个数
int e;//边数
int **array;//储存图的联通信息的邻接矩阵
string *info;//结点的信息
bool *visit;//判断该结点是否访问过,false:没有访问过,true:访问过
public:
Graph_a();
~Graph_a();
void print_gra();
void dfs(int index);//深度遍历算法的实现
void dfs_array(int begin);//深度遍历该图
};
//构造函数
Graph_a::Graph_a()
{
cout<<" 请输入图的顶点的个数:"<<endl;
cin>>num;
cout<<" 请输入图的边数:"<<endl;
cin>>e;
//初始化visit,设置每个结点都未访问过
visit=new bool[num];
;i<num;++i)
visit[i]=false;
//初始换存储结点信息的数组
info=new string[num];//new 析构函数中释放
cout<<" 请输入每个顶点的信息:"<<endl;
;i<num;++i)
cin>>info[i];
cout<<" 请输入每条边的两个顶点的编号:"<<endl;
int **e_info=new int*[e];//临时的数组构造函数结束可释放
;i<e;++i)
{
//cout<<"i:"<<i<<endl;
e_info[i]=];
cin>>e_info[i][]>>e_info[i][];
}
//为邻接矩阵开辟空间并初始化
array=new int*[num];//为邻接矩阵开辟空间,一维数组
;i<num;++i)
{
array[i]=new int[num];//二维数组
;j<num;++j)
array[i][j]=;
}
//根据无向图的边的起始坐标和结束坐标构建邻接矩阵,数组中下标均是从0开始,所以需要减1
;i<e;++i)
array[e_info[i][]-][e_info[i][]-]=;
//释放e_info
;i<e;++i)
delete []e_info[i];
delete []e_info;
}
//析构函数
Graph_a::~Graph_a()
{
//释放邻接矩阵
;i<num;++i)
delete []array[i];
delete []array;
delete []info;//释放存储结点信息的数组
delete []visit;//释放标记数组
}
//打印该图的邻接矩阵
void Graph_a::print_gra()
{
cout<<" 该图的邻接矩阵是:"<<endl;
;i<num;++i)
{
;j<num;++j)
cout<<array[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
//深度遍历该图
void Graph_a::dfs_array(int begin)
{
dfs(begin);
//如果是非连通图,那么需要把结点再遍历一边,保证全部结点都被访问
;i<num;++i)
if(!visit[i])
dfs(i);
}
//深度遍历算法实现
void Graph_a::dfs(int index)
{
cout<<info[index]<<" ";
//标记该结点为访问过
visit[index]=true;
;i<num;++i)//值为0或无穷大表示两点之间没有连通
||array[index][i]==INF)
continue;
else if(!visit[i])
dfs(i);
}
/***************图用邻接表表示***************/
//邻接表中处头结点外的每个结点
typedef struct Node
{
int index;//该边的另一个顶点在顶点表中的下标
Node *next;//依附该顶点的下一条边信息
}Node;
//邻接表中的头结点
typedef struct Head_node
{
string data;
Node *first;//依附顶点的第一条边的信息
}Head_node;
//封装成邻接表:就是对每个结点建一条链表
class Graph_l
{
private:
int num;//顶点数
int e;//边数
bool *visit;
Head_node *node;
public:
Graph_l();
~Graph_l();
void print_g();
void dfs_l(int begin);
void dfs(int index);
};
//构造函数
Graph_l::Graph_l()
{
cout<<" 请输入图的顶点的个数:"<<endl;
cin>>num;
cout<<" 请输入图的边数:"<<endl;
cin>>e;
//初始化visit,设置每个结点都未访问过
visit=new bool[num];
;i<num;++i)
visit[i]=false;
//为邻接表动态申请存储空间,并初始化
node=new Head_node[num];
cout<<" 请输入每个结点的信息:"<<endl;
;i<num;++i)
{
cin>>node[i].data;
node[i].first=NULL;
}
cout<<" 请输入每条边的两个顶点的编号:"<<endl;
int **e_info=new int*[e];//临时的数组构造函数结束可释放
;i<e;++i)
{
e_info[i]=];
cin>>e_info[i][]>>e_info[i][];//e_info[i][0]存放边的起始点,e_info[i][1]存放边的结束点
}
;i<e;++i)
{
Node *next=new Node;
next->index=e_info[i][]-;
next->next=NULL;
//判断该顶点的边是否有依附
]-].first==NULL)
node[e_info[i][]-].first=next;
else//寻找邻接表的最后一个节点
{
Node *now;
now=node[e_info[i][]-].first;
while(now->next)
now=now->next;
now->next=next;
}
}
//释放e_info
;i<num;++i)
delete []e_info[i];
delete []e_info;
}
//析构函数
Graph_l::~Graph_l()
{
delete []node;
delete []visit;
}
//打印邻接链表的函数
void Graph_l::print_g()
{
cout<<" 该图的邻接表表示为:"<<endl;
;i<num;++i)
{
//输出结点的数据
cout<<node[i].data<<" ";
//依附头节点的第一个结点
Node *now=node[i].first;
while(now)
{
//输出依附该边的结点的另一个坐标
cout<<now->index<<" ";
now=now->next;
}
cout<<endl;
}
cout<<endl;
}
//深度优先搜索邻接表
void Graph_l::dfs_l(int begin)
{
dfs(begin);
;i<num;++i)
if(visit[i]==false)
dfs(i);
}
//深度优先搜索算法实现
void Graph_l::dfs(int index)
{
cout<<node[index].data<<" ";
visit[index]=true;
Node *next=node[index].first;
while(next)
{
if(!visit[next->index])
dfs(next->index);
else
next=next->next;
}
}
int main()
{
//图的邻接矩阵
Graph_a g;
g.print_gra();
g.dfs_array();
//图的邻接表
Graph_l G;
G.print_g();
G.dfs_l();
;
}
BFS
广度优先搜索是指按照广度得方向搜索,类似于树的按层遍历,是树的按层遍历的推广
1.从图中某个顶点v0出发,首先访问v0
2.依次访问v0各个未被访问的邻结点
3.分别从这些邻接点(端点)出发,依次访问他各个问呗访问的邻接点(新的端点),访问时保证:如果vi和vj为当前端结点,且vi在vj前被访问,则vi所有未被访问的邻接点应在vj所有未被访问的邻接点
前访问,重复步骤3,直到所有端结点的邻接点都被访问过。
如果还有其他节点未被访问,选一个未被访问的顶点作为起始点,重复上述过程,直到所有节点都被访问过.
#include <iostream>
#include <queue>
#define INF 0x3f3f
using namespace std;
/***************图用邻接矩阵表示***************/
class Graph_a
{
private:
int num;//顶点个数
int e;//边数
int **array;//储存图的联通信息的邻接矩阵
string *info;//结点的信息
bool *visit;//判断该结点是否访问过,false:没有访问过,true:访问过
public:
Graph_a();
~Graph_a();
void print_gra();
void dfs(int begin);//深度遍历算法的实现
};
//构造函数
Graph_a::Graph_a()
{
cout<<" 请输入图的顶点的个数:"<<endl;
cin>>num;
cout<<" 请输入图的边数:"<<endl;
cin>>e;
//初始化visit,设置每个结点都未访问过
visit=new bool[num];
;i<num;++i)
visit[i]=false;
//初始换存储结点信息的数组
info=new string[num];//new 析构函数中释放
cout<<" 请输入每个顶点的信息:"<<endl;
;i<num;++i)
cin>>info[i];
cout<<" 请输入每条边的两个顶点的编号:"<<endl;
int **e_info=new int*[e];//临时的数组构造函数结束可释放
;i<e;++i)
{
//cout<<"i:"<<i<<endl;
e_info[i]=];
cin>>e_info[i][]>>e_info[i][];
}
//为邻接矩阵开辟空间并初始化
array=new int*[num];//为邻接矩阵开辟空间,一维数组
;i<num;++i)
{
array[i]=new int[num];//二维数组
;j<num;++j)
array[i][j]=;
}
//根据无向图的边的起始坐标和结束坐标构建邻接矩阵,数组中下标均是从0开始,所以需要减1
;i<e;++i)
array[e_info[i][]-][e_info[i][]-]=;
//释放e_info
;i<e;++i)
delete []e_info[i];
delete []e_info;
}
//析构函数
Graph_a::~Graph_a()
{
//释放邻接矩阵
;i<num;++i)
delete []array[i];
delete []array;
delete []info;//释放存储结点信息的数组
delete []visit;//释放标记数组
}
//打印该图的邻接矩阵
void Graph_a::print_gra()
{
cout<<" 该图的邻接矩阵是:"<<endl;
;i<num;++i)
{
;j<num;++j)
cout<<array[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
//深度遍历算法实现
void Graph_a::dfs(int begin)
{
queue<int> q;//BFS类似于树的按层遍历,所以用queue
//图可能是非联通的,所以要循环遍历每个顶点
;i<num;++i)//不一定是从第一个点开始遍历,所以要对输入(下标+点的个数-1)%点的个数
+i]%num)
{
cout<<info[(begin-+i)%num]<<" ";
visit[(begin-+i)%num]=true;//把该结点标记为访问过,也就是图中的边的起始下标
q.push((begin-+i)%num);//把该点的下标存入对列中
while(!q.empty())
{
int t=q.front();//图中边的起始下标
q.pop();
;j<num;++j)
||array[t][j]==INF)
continue;
else if(!visit[j])
{
cout<<info[j]<<" ";
visit[j]=true;
q.push(j);
}
}
}
}
/***************图用邻接表表示***************/
//邻接表中处头结点外的每个结点
typedef struct Node
{
int index;//该边的另一个顶点在顶点表中的下标
Node *next;//依附该顶点的下一条边信息
}Node;
//邻接表中的头结点
typedef struct Head_node
{
string data;
Node *first;//依附顶点的第一条边的信息
}Head_node;
//封装成邻接表:就是对每个结点建一条链表
class Graph_l
{
private:
int num;//顶点数
int e;//边数
bool *visit;
Head_node *node;
public:
Graph_l();
~Graph_l();
void print_g();
void dfs(int begin);
};
//构造函数
Graph_l::Graph_l()
{
cout<<" 请输入图的顶点的个数:"<<endl;
cin>>num;
cout<<" 请输入图的边数:"<<endl;
cin>>e;
//初始化visit,设置每个结点都未访问过
visit=new bool[num];
;i<num;++i)
visit[i]=false;
//为邻接表动态申请存储空间,并初始化
node=new Head_node[num];
cout<<" 请输入每个结点的信息:"<<endl;
;i<num;++i)
{
cin>>node[i].data;
node[i].first=NULL;
}
cout<<" 请输入每条边的两个顶点的编号:"<<endl;
int **e_info=new int*[e];//临时的数组构造函数结束可释放
;i<e;++i)
{
e_info[i]=];
cin>>e_info[i][]>>e_info[i][];//e_info[i][0]存放边的起始点,e_info[i][1]存放边的结束点
}
;i<e;++i)
{
Node *next=new Node;
next->index=e_info[i][]-;
next->next=NULL;
//判断该顶点的边是否有依附
]-].first==NULL)
node[e_info[i][]-].first=next;
else//寻找邻接表的最后一个节点
{
Node *now;
now=node[e_info[i][]-].first;
while(now->next)
now=now->next;
now->next=next;
}
}
//释放e_info
;i<num;++i)
delete []e_info[i];
delete []e_info;
}
//析构函数
Graph_l::~Graph_l()
{
delete []node;
delete []visit;
}
//打印邻接链表的函数
void Graph_l::print_g()
{
cout<<" 该图的邻接表表示为:"<<endl;
;i<num;++i)
{
//输出结点的数据
cout<<node[i].data<<" ";
//依附头节点的第一个结点
Node *now=node[i].first;
while(now)
{
//输出依附该边的结点的另一个坐标
cout<<now->index<<" ";
now=now->next;
}
cout<<endl;
}
cout<<endl;
}
//深度优先搜索算法实现
void Graph_l::dfs(int begin)
{
queue<int> q;
;i<num;++i)
+i]%num)
{
cout<<node[(begin-+i)%num].data<<" ";
visit[(begin-+i)%num]=true;
q.push((begin-+i)%num);
while(!q.empty())
{
int t=q.front();
q.pop();
Node *next=node[t].first;
while(next)
{
if(!visit[next->index])
{
cout<<node[next->index].data<<" ";
visit[next->index]=true;
q.push(next->index);
}
next=next->next;
}
}
}
}
int main()
{
//图的邻接矩阵
Graph_a g;
g.print_gra();
g.dfs();
//图的邻接表
Graph_l G;
G.print_g();
G.dfs();
;
}
以上都是基于无向图的写法,有向图的写法在创建邻接表或邻接矩阵时,遍历时稍加修改即可
DFS&&BFS的更多相关文章
- DFS/BFS+思维 HDOJ 5325 Crazy Bobo
题目传送门 /* 题意:给一个树,节点上有权值,问最多能找出多少个点满足在树上是连通的并且按照权值排序后相邻的点 在树上的路径权值都小于这两个点 DFS/BFS+思维:按照权值的大小,从小的到大的连有 ...
- 【DFS/BFS】NYOJ-58-最少步数(迷宫最短路径问题)
[题目链接:NYOJ-58] 经典的搜索问题,想必这题用广搜的会比较多,所以我首先使的也是广搜,但其实深搜同样也是可以的. 不考虑剪枝的话,两种方法实践消耗相同,但是深搜相比广搜内存低一点. 我想,因 ...
- ID(dfs+bfs)-hdu-4127-Flood-it!
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4127 题目意思: 给n*n的方格,每个格子有一种颜色(0~5),每次可以选择一种颜色,使得和左上角相 ...
- [LeetCode] 130. Surrounded Regions_Medium tag: DFS/BFS
Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. A reg ...
- HDU 4771 (DFS+BFS)
Problem Description Harry Potter has some precious. For example, his invisible robe, his wand and hi ...
- DFS/BFS视频讲解
视频链接:https://www.bilibili.com/video/av12019553?share_medium=android&share_source=qq&bbid=XZ7 ...
- POJ 3083 -- Children of the Candy Corn(DFS+BFS)TLE
POJ 3083 -- Children of the Candy Corn(DFS+BFS) 题意: 给定一个迷宫,S是起点,E是终点,#是墙不可走,.可以走 1)先输出左转优先时,从S到E的步数 ...
- [LeetCode]695. 岛屿的最大面积(DFS/BFS)、200. 岛屿数量(DFS/BFS待做/并差集待做)
695. 岛屿的最大面积 题目 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被 ...
- POJ2308连连看dfs+bfs+优化
DFS+BFS+MAP+剪枝 题意: 就是给你一个10*10的连连看状态,然后问你最后能不能全部消没? 思路: 首先要明确这是一个搜索题目,还有就是关键的一点就是连连看这个游戏是 ...
- ACM/ICPC 之 靠墙走-DFS+BFS(POJ3083)
//POJ3083 //DFS求靠左墙(右墙)走的路径长+BFS求最短路 //Time:0Ms Memory:716K #include<iostream> #include<cst ...
随机推荐
- Ubuntu安装 jdk.rpm 报错问题解决
报错问题出现原因 第一次使用Ubuntu操作系统,很多命令及软件安装方式与以往使用的Linux操作系统(CentOS)有很大区别.现在总结使用Ubuntu在安装JDK中,遇到的问题及解决方法. roo ...
- Nature 为引,一文看懂个体化肿瘤疫苗前世今生
进入2017年,当红辣子鸡PD-1疗法,一路横扫多个适应症.而CAR-T治疗的“小车”在获得FDA专委会推荐后也已经走上高速路,成为免疫治疗又一里程碑事件.PD-1.CAR-T之后,下一个免疫治疗产品 ...
- 连接数据库的DBUtils工具类
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...
- Android 引用资源
比如在 strings.xml 中找到的 Hello world!字符串,我们有两种方式可以引用它: 1. 在代码中通过 R.string.hello_world 可以获得该字符串的引用: 2. 在 ...
- python 在列表中添加元组元素,按照元组第一个值进行排序
>>> import bisect >>> scores = [(, , , , 'python')] >>> bisect.insort(sco ...
- 中国铁路基于Intel架构超大规模OpenStack行业云的性能优化研究
1. 项目简介 铁路作为一种大众化的交通工具和非常重要的货物运输方式,其业务规模庞大.覆盖全国.服务全国各族人民.铁路面向公众提供的服务业务,主要是客运和货运两大类,且每年365天.每天7*24小时连 ...
- spring boot: 热部署(一) run as – java application (spring-loader-1.2.4.RELEASE.jar)
spring boot: 热部署(一) run as – java application (spring-loader-1.2.4.RELEASE.jar) 如果使用的run as – java a ...
- Jmeter非GUI模式启动
首先我们需要了解,GUI和非GUI模式启动Jmeter对测试的影响:Jmeter可视化界面及监听器展示结果需要消耗负载资源,从而导致,在大并发的情况下GUI方式会导致负载机资源紧张,对性能造成影响 e ...
- Android中Tablayout设置下划线宽度 和 dp和px之间进行相互转换
开发中遇到了一个问题,Tablayout设置下换线长度,看了点资料,分享给大家. 效果图: 直接贴代码(要在tabLayout添加完所有的tab后调用) public vo ...
- js做小数运算精度问题
当js做小数运算时存在bug,大概是因为二进制和十进制转换之间的关系. bug如图 解决方案 1.运算结果后,乘以100再除以100.网上推荐这种方法但是乘以1000再除以1000依然存在精度问题 2 ...