图的DFS和BFS(邻接表)
用C++实现图的DFS和BFS(邻接表)
概述
图的储存方式有邻接矩阵和邻接表储存两种。由于邻接表的实现需要用到抽象数据结构里的链表,故稍微麻烦一些。C++自带的STL可以方便的实现List,使算法的实现变得简单起来
算法概述

为了让我们的算法更有普适性,我们将非连通图也考虑在内。其实,要想遍历到类似于图中5,6节点这种孤岛节点,只需要依次按编号遍历顺序所有节点,如果某节点没有访问(book数组标记值为0),则从该节点开始深度优先搜索或广度优先搜索;等一次深搜或广搜完毕后,继续依次按照编号顺序遍历节点,选择从一个没访问过的结点开始再次深搜或广搜。。。如此知道把所有节点都遍历完。
代码
1.图抽象数据类型的声明,除了构造函数和析构函数之外,提供3个对外接口,分别实现递归DFS,BFS和非递归DFS(用STL栈实现)
using namespace std;
struct Graph{
//储存节点的邻接表
vector<list<int>> vertex;
//标记数组
bool book[100];
//n代表总节点个数
Graph(int n);
~Graph();
//对外接口,算法的驱动函数
void DFS_recursion_boost();
void BFS_boost();
void DFS_stack_boost();
private://内部算法实现
void DFS_recursion(int cur);
void BFS(int cur);
void DFS_stack(int cur);
};
2.图的构造函数和析构函数实现
Graph::Graph(int n){
vertex.resize(n);
for(int i=0;i<n;++i){
int adj;
cout<<"请输入"<<i<<"号节点邻接链表(以-1表示结束输入)"<<endl;
cin>>adj;
while(adj!=-1){
vertex[i].push_back(adj);
cin>>adj;
}
}
memset(book,0,sizeof(book));
}
Graph::~Graph(){
vertex.clear();
}
3.图的递归DFS调用接口及其实现函数
void Graph::DFS_recursion_boost(){
for(int i=0;i<vertex.size();++i){
DFS_recursion(i);
}
}
void Graph::DFS_recursion(int cur){
if(book[cur]==1) return;
book[cur]=1;
cout<<cur;
for(auto iter=vertex[cur].begin();iter!=vertex[cur].end();++iter){
if(book[*iter]==0){
DFS_recursion(*iter);
}
}
}
4.图的BFS调用接口及其实现函数
void Graph::BFS_boost(){
for(int i=0;i<vertex.size();++i){
BFS(i);
}
}
void Graph::BFS(int cur){
queue<int> q;
if(book[cur]==0){
q.push(cur);
}
while(!q.empty()){
int front=q.front();
q.pop();
cout<<front;
book[front]=1;
for(auto iter=vertex[front].begin();iter!=vertex[front].end();++iter){
if(book[*iter]==0){
q.push(*iter);
}
}
}
}
5.图的非递归DFS及其实现函数
void Graph::DFS_stack_boost(){
for(int i=0;i<vertex.size();++i){
DFS_stack(i);
}
}
void Graph::DFS_stack(int cur)
{
stack<int> s;
if(book[cur]==0){
s.push(cur);
}
while(!s.empty()){
int top=s.top();
if(book[top]==0){
book[top]=1;
cout<<top;
}
else{
s.pop();
// top=s.top();为何不要?
}
for(auto iter=vertex[top].begin();iter!=vertex[top].end();++iter){
if(book[*iter]==0){
s.push(*iter);
break;
}
}
}
}
6.主函数测试(注意,每次遍历后要把标记数组初始化为0)
int main(){
Graph G(7);
cout<<"递归DFS:"<<endl;
G.DFS_recursion_boost();
memset(G.book,0,100);
cout<<endl;
cout<<"BFS:"<<endl;
G.BFS_boost();
memset(G.book,0,100);
cout<<endl;
cout<<"非递归BFS:"<<endl;
G.DFS_stack_boost();
memset(G.book,0,100);
cout<<endl;
system("pause");
return 0;
}
输出

图的DFS和BFS(邻接表)的更多相关文章
- 数据结构(11) -- 邻接表存储图的DFS和BFS
/////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...
- 图的DFS与BFS
图的DFS与BFS(C++) 概述 大一学生,作为我的第一篇Blog,准备记录一下图的基本操作:图的创建与遍历.请大佬多多包涵勿喷. 图可以采用邻接表,邻接矩阵,十字链表等多种储存结构进行储存,这里为 ...
- Java数据结构——图的DFS和BFS
1.图的DFS: 即Breadth First Search,深度优先搜索是从起始顶点开始,递归访问其所有邻近节点,比如A节点是其第一个邻近节点,而B节点又是A的一个邻近节点,则DFS访问A节点后再访 ...
- 【数据结构】【图文】【oj习题】 图的拓扑排序(邻接表)
拓扑排序: 按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系,由此所得顶点的线性序列称之为拓扑有序序列.显然对于有回路的有向图得不 ...
- 图的基本操作(基于邻接表):图的构造,深搜(DFS),广搜(BFS)
#include <iostream> #include <string> #include <queue> using namespace std; //表结点 ...
- [数据结构]图的DFS和BFS的两种实现方式
深度优先搜索 深度优先搜索,我们以无向图为例. 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发, ...
- 图的DFS与BFS遍历
一.图的基本概念 1.邻接点:对于无向图无v1 与v2之间有一条弧,则称v1与v2互为邻接点:对于有向图而言<v1,v2>代表有一条从v1到v2的弧,则称v2为v1的邻接点. 2.度:就是 ...
- bfs 邻接表(需要优化 可能会RE *【模板】)
//---基于邻接表的bfs #include <stdio.h> #include <string.h> #include <iostream> #include ...
- hdu 4707 Pet(DFS && 邻接表)
Pet Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
随机推荐
- 团队转型,Scrum与DevOps要如何取舍?
团队在践行敏捷的过程中,会有多种选择:Scrum.XP.Kanban.Crystal.精益生产.规模化敏捷等,其中最流行的敏捷开发方法当属Scrum.正因如此,大部分人对其产生了刻板印象:认为敏捷就是 ...
- Centos7安装Docker1.9.1
1.先检查是否安装旧版本docker [root@registry ~]# rpm -qa|grep docker 我这里没有安装,如果安装,请rpm -e 卸载2.编辑docker.repo文件,写 ...
- OnePill本地保存用户的结构
sharedPreferences存储的数据 int Code code 表示当前用户的类别:医生为1,用户为2. Sting user user 存储当前user的json字符串 String do ...
- 关于调用三方平台接口与推送接口的总结<二>(2020.7.27)
前言:本篇博客是接着上篇总结写的,想了解怎么对接第三方平台接口的同学可以看我上一篇博客,地址是 https://www.cnblogs.com/alanturingson/p/13377500.ht ...
- Kaggle 入门题-泰坦尼克号灾难存活预测
这个题目的背景概况来讲就是基于泰坦尼克号这个事件,然后大量的人员不幸淹没在这个海难中,也有少部分人员在这次事件之中存活,然后这个问题提供了一些人员的信息如姓名.年龄.性别.票价,所在客舱等等一些信息, ...
- Vue数据产生变化需要页面渲染完之后执行某操作
1.数据产生变化或者页面需要vue数据渲染完之后加载的东西 Vue.nextTick(function () { alert(123); }); 2 调用vue方法 --------------Vue ...
- Python time ctime()方法
描述 Python time ctime() 函数把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式.高佣联盟 www.cgewang.com 如果参数未给或者为None的时候, ...
- PHP libxml_clear_errors() 函数
定义和用法 libxml_clear_errors() 函数清空 libxml 错误缓冲. 语法 libxml_clear_errors() 实例 <?phplibxml_clear_error ...
- luogu P5826 【模板】子序列自动机 主席树 vector 二分
LINK:子序列自动机 想了一些很有趣的做法. dp 容易看出 f[i][j]表示前i个数匹配了j个数的dp 不过复杂度很高. 贪心 容易想到匹配的时候每个数字尽量往前匹配 这样显然是最优的 复杂度Q ...
- 类加载Class Loading
JVM 何时.如何把 Class 文件加载到内存,形成可以直接使用的 Java 类型,并开始执行代码? 类的生命周期 加载 - 连接(验证.准备.解析)- 初始化 - 使用 - 卸载. 注意,加载 ...