列出连通集(DFS及BFS遍历图) -- 数据结构
题目:
给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。
输出格式:
按照 “ { v1, v2, v3, ... ,vk } ”的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
1 v2 ... vk }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
输入样例:
8 6
0 7
0 1
2 0
4 1
2 4
3 5
输出样例:
{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
分析:
当读完这道题之后,很容易就能够知道我们需要做的两件事:①构建图 ②DFS遍历和BFS遍历
这里为了方便起见(同时数据量并不大),这里将采用邻接矩阵存储图。
代码:
对结构体结构的定义:
#define max 10
typedef int vertex_type;
typedef int edge_type;
typedef struct graph_matrix{
int n, e;//顶点数;边数
vertex_type vexs[max];//顶点一维数组
edge_type edges[max][max];//邻接矩阵二维数组,元素类型为vector<vertex_type>
}gm;
全局变量visit[]
//visit[]数组;全局变量
int visit[max] = {};
①构建图
//创建图
void create_gm(gm &gm)
{
cin>>gm.n>>gm.e;
memset(gm.edges, , sizeof(gm.edges));
for(int i=; i<gm.n; i++){
gm.vexs[i] = i;
} //输入边数据
int a, b;
for(int i=; i<gm.e; i++){
cin>>a>>b;
gm.edges[a][b] = ;
gm.edges[b][a] = ;
}
}
②DFS遍历
//深度优先
//id: 以id为起始点
void DFS(gm &gm, int id)
{
visit[id] = ;
cout<<id<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][id] == && visit[i] == ){
DFS(gm, i);
}
}
}
③BFS遍历
//宽度优先
void BFS(gm &gm, int id)
{
visit[id] = ;
queue<int> qu;
qu.push(id);
while(qu.size() != ){
int mark = qu.front();
qu.pop();
cout<<mark<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][mark] == && visit[i] == ){
visit[i] = ;
qu.push(i);
}
}
}
}
全部的代码:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std; #define max 10
typedef int vertex_type;
typedef int edge_type;
typedef struct graph_matrix{
int n, e;//顶点数;边数
vertex_type vexs[max];//顶点一维数组
edge_type edges[max][max];//邻接矩阵二维数组,元素类型为vector<vertex_type>
}gm; //函数声明
void create_gm(gm &gm);
void DFS(gm &gm, int id);
void BFS(gm &gm, int id); //visit[]数组;全局变量
int visit[max] = {}; int main()
{
gm gm;//定义一个叫做gm的邻接矩阵
create_gm(gm); //调用DFS遍历
for(int i=; i<gm.n; i++){
if(visit[i] == )continue;
cout<<"{ ";
DFS(gm ,i);
cout<<"}"<<endl;
} //重置visit[]数组
memset(visit, , sizeof(visit)); //调用BFS遍历
for(int i=; i<gm.n; i++){
if(visit[i] == ){
cout<<"{ ";
BFS(gm ,i);
cout<<"}"<<endl;
}
}
return ;
} //创建图
void create_gm(gm &gm)
{
cin>>gm.n>>gm.e;
memset(gm.edges, , sizeof(gm.edges));
for(int i=; i<gm.n; i++){
gm.vexs[i] = i;
} //输入边数据
int a, b;
for(int i=; i<gm.e; i++){
cin>>a>>b;
gm.edges[a][b] = ;
gm.edges[b][a] = ;
}
} //深度优先
void DFS(gm &gm, int id)
{
visit[id] = ;
cout<<id<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][id] == && visit[i] == ){
DFS(gm, i);
}
}
} //宽度优先
void BFS(gm &gm, int id)
{
visit[id] = ;
queue<int> qu;
qu.push(id);
while(qu.size() != ){
int mark = qu.front();
qu.pop();
cout<<mark<<" ";
for(int i=; i<gm.n; i++){
if(gm.edges[i][mark] == && visit[i] == ){
visit[i] = ;
qu.push(i);
}
}
}
}
ALL
总结:
在这个题目中主要是对之前在树章节中,对关于树的前序遍历(DFS)和层次遍历(BFS)的知识迁移。
① DFS往往会运用到栈来进行实现,而递归就是利用栈的一个实现方法,递归特性使算法代码简洁的同时,也使算法理解困难,
所以对于我这种初学者来说画图和动手实践是最好的学习方法。
例子:“走迷宫,你没有办法用分身术同时走进多叉道路中,不撞南墙不回头。”(来源自网络)
② BFS则是要运用到队列,程序流程相对于DFS来说更为清晰。
例子:“当你眼镜掉了,你趴在地上找,你总是会先摸靠近你的地方,如果没有,再摸远一点的地方。”(来源自网络)
如何对已有知识的新运用也是能力提升的一种,在此我也对DFS和BFS有了更深一层的理解。
嘻嘻:)
列出连通集(DFS及BFS遍历图) -- 数据结构的更多相关文章
- 图的DFS与BFS遍历
一.图的基本概念 1.邻接点:对于无向图无v1 与v2之间有一条弧,则称v1与v2互为邻接点:对于有向图而言<v1,v2>代表有一条从v1到v2的弧,则称v2为v1的邻接点. 2.度:就是 ...
- 邻接矩阵实现图的存储,DFS,BFS遍历
图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...
- 数据结构上机实验dfs&&bfs遍历图
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #inc ...
- DFS和BFS遍历的问题
来自https://github.com/soulmachine/leetcode 广度优先搜索 输入数据:没有什么特征,不像dfs需要有递归的性质.如果是树/图,概率更大. 状态转换图:数或者DAG ...
- 判断图连通的三种方法——dfs,bfs,并查集
Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...
- 图的bfs遍历模板(邻接矩阵存储和邻接表存储)
bfs遍历图模板伪代码: bfs(u){ //遍历u所在的连通块 queue q; //将u入队 inq[u] = true; while (q非空){ //取出q的队首元素u进行访问 for (从u ...
- 数据结构(三十二)图的遍历(DFS、BFS)
图的遍历和树的遍历类似.图的遍历是指从图中的某个顶点出发,对图中的所有顶点访问且仅访问一次的过程.通常有两种遍历次序方案:深度优先遍历和广度优先遍历. 一.深度优先遍历 深度优先遍历(Depth_Fi ...
- [数据结构]图的DFS和BFS的两种实现方式
深度优先搜索 深度优先搜索,我们以无向图为例. 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发, ...
- PTA 2-1 列出连通集【DFS+BFS基础】
给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N−1编号.进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点. 输入格式: 输入第1 ...
随机推荐
- Java多线程和并发(五),线程的状态
目录 1.线程的六个状态 2.sleep和wait的区别 3.锁池(EntryList)和等待池(WaitSet) 4.notify和notifyall的区别 五.线程的状态 1.线程的六个状态 2. ...
- TTTTTTTTTTTT 百度之星D map+hash
Problem D Accepts: 2806 Submissions: 8458 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 6 ...
- 「SDOI2017」硬币游戏
题目链接 问题分析 首先一个显然的做法就是建出AC自动机,然后高斯消元.但是这样的复杂度是\(O(n^3m^3)\)的. 我们发现其实只需要求AC自动机上\(n\)个状态的概率,而其余的概率是没有用的 ...
- oracle判断一个字段为空
比如 insert into table a (a1,b1)values("a1",''); 对于这种情况,因为表里存的是'',其实是没有内容的,要查询这个字段,不能直接使用 se ...
- kill 与 killall和过滤后杀掉
1.绝杀 kill -9 PID 杀掉单一进程 例如:kill -9 pid号 同意的 kill -s SIGKILL 这个强大和危险的命令迫使进程在运行时突然终止,进程在结束后不能自我清 ...
- C++入门经典-例3.21-goto语句实现循环
1:代码如下: // 3.21.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...
- linux各种中文乱码解决办法整理
2016年03月21日 15:52:05 阅读数:30812 远程登录服务器用vim在终端下编辑查看文件经常会遇见各种中文乱码问题.做如下设置可基本解决vim中文乱码问题 首先查看系统对中文的支持lo ...
- express node 框架介绍
开篇先声明一个重点: 就是论文件模块的重要性,之前我一直以为 fs 模块不重要,后来遇到了问题,才发现我之前的自以为是是多么愚蠢的一件事,我现在知道了 fs 模块的重要性 fs 模块:用于对文件的操作 ...
- DB2日常管理
执行时间最长的10条SQL语句(按时间降序排列),可保存为脚本方便调用:db2 "SELECT rows_read / (num_executions + 1) as avg_rows_re ...
- TNS:could not resolve the connect identifier specified解决办法
添加环境变量解决:TNS_ADMIN ->> D:\OracleDB\product\11.2.0\dbhome_1\NETWORK\ADMIN