图的DFS与BFS(C++)


概述

大一学生,作为我的第一篇Blog,准备记录一下图的基本操作:图的创建与遍历。请大佬多多包涵勿喷。

图可以采用邻接表,邻接矩阵,十字链表等多种储存结构进行储存,这里为了方便演示算法,采用邻接矩阵。 图为边的权值都默认为1的无向图 。

国内大学现行教材大多是C语言实现,然而C语言其实并不适合实现ADT,故这里使用和C语言相近的C++,引入OOP的机制进行类封装,更直观和容易理解。


代码

1.首先,因为要用到DFS,这里分别采用递归的方式和非递归方式(要用到STL提供的栈),故引入头文件,BFS利用队列,引用头文件queue。

接着对图的抽象数据类型进行声明,类的属性有两个,分别是储存顶点容器vertex和储存边的容器edge,提供3个接口,分别对应三种遍历方式。

#include<iostream>
#include<queue>
#include<vector>
#include<stack>
#include<mem.h>
int inf=-9999;
using namespace std; //为了增强复用性,这里封装成类模板,虚拟类型为T
template <class T>
struct Graph{
//存放顶点
vector<T> vertex;
//存放边
vector<vector<int>> edge;
//标记数组
bool book[100];
//构造函数
Graph(int n,int m);
//析构函数
~Graph();
//递归深度优先遍历
void DFS_recursion(int cur);
//非递归深度优先遍历
void DFS_stack(int cur);
//广度优先遍历
void BFS(int cur);
};

2.接着,定义Graph类的构造函数与析构函数,构造函数传入两个参数,对应图的定点数和边数,并创建一个book标记数组来记录定点是否访顶点,初始化book全部置为0,表示顶点都没访问。还有一点值得注意的是:这里为了方便,直接将顶点的数值设置为顶点的下标。

template <class T>
Graph<T>::Graph(int n,int m){
//为了使顶点对应的下标符合人类思维(从1起),这里的容器大小分配为n+1;
vertex.resize(n+1);
edge.resize(n+1);
for(int i=0;i<n+1;i++){
edge[i].resize(n+1);
}
//初始化邻接矩阵
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) edge[i][j]=0;
else edge[i][j]=inf;
}
}
cout<<"请输入各条边的两个邻点"<<endl;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
//这里使用无向图,故边应用edge[a][b]=edge[b][a]=1;初始化
edge[a][b]=edge[b][a]=1;
}
////因为各顶点的值为设为int类型,故为了方便,将各顶点的值初始化为其下标
for(int i=1;i<=m;i++){
vertex[i]=i;
}
//标记数组初始化
memset(book,0,100);
} template <class T>
Graph<T>:: ~Graph(){
vertex.clear();
edge.clear();
}

3.以下分别是3种不同的图的遍历方法的实现:

template <class T>
void Graph<T>::DFS_recursion(int cur){
book[cur]=true;
cout<<vertex[cur];
for(int i=0;i<vertex.size();i++){
if(edge[cur][i]==1&&book[i]==0){
DFS_recursion(i);
}
}
} template <class T>
void Graph<T>::DFS_stack(int cur){
stack<int> s;
s.push(cur);
while(!s.empty()){
int top=s.top();
if(book[top]==0){
cout<<top;
book[top]=1;
}
else s.pop();
for(int i=0;i<vertex.size();i++){
if(book[i]==0&&edge[top][i]==1){
s.push(i);
break;
}
}
}
return;
} template <class T>
void Graph<T>::BFS(int cur){
queue<int> q;
q.push(cur);
book[cur]=1;
while(!q.empty()){
int front=q.front();
q.pop();
cout<<vertex[front];
for(int i=0;i<vertex.size();i++){
if(edge[front][i]==1&&book[i]==0){
q.push(i);
book[i]=1;
}
}
}
}

4.最后是测试部分:主函数创建实例,并调用类的方法完成对图的操作。这里初始化为5个节点5条边,权值都默认为1。调用时都从顶点1开始便遍历。注意:每次便利完成后都要用memset将book标记数组全部置0,表示没访问过。

int main(){
//将类模板实例化为模板类,再将模板类实例化为一个对象
Graph<T>* G=new Graph<int>(5,5); cout<<"深度优先遍历(递归)如下:"<<endl;
G->DFS_recursion(1);
memset(G->book,0,100);
cout<<endl; cout<<"深度优先遍历(非递归)如下:"<<endl;
G->DFS_stack(1);
memset(G->book,0,100);
cout<<endl; cout<<"广度优先队列遍历如下:"<<endl;
G->BFS(1);
cout<<endl; system("pause");
return 0;
}

输出结果

测试控制台输出如下:

图的DFS与BFS的更多相关文章

  1. 图的DFS和BFS(邻接表)

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

  2. Java数据结构——图的DFS和BFS

    1.图的DFS: 即Breadth First Search,深度优先搜索是从起始顶点开始,递归访问其所有邻近节点,比如A节点是其第一个邻近节点,而B节点又是A的一个邻近节点,则DFS访问A节点后再访 ...

  3. 数据结构(11) -- 邻接表存储图的DFS和BFS

    /////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...

  4. [数据结构]图的DFS和BFS的两种实现方式

    深度优先搜索 深度优先搜索,我们以无向图为例. 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发, ...

  5. 图的DFS与BFS遍历

    一.图的基本概念 1.邻接点:对于无向图无v1 与v2之间有一条弧,则称v1与v2互为邻接点:对于有向图而言<v1,v2>代表有一条从v1到v2的弧,则称v2为v1的邻接点. 2.度:就是 ...

  6. 树的常见算法&图的DFS和BFS

    树及二叉树: 树:(数据结构中常见的树) 树的定义

  7. 图、dfs、bfs

    graphdfsbfs 1.clone graph2.copy list with random pointer3.topological sorting4.permutations5.subsets ...

  8. 树与图的DFS与BFS

    树的DFS 题目:https://www.acwing.com/problem/content/848/ 代码 #include<bits/stdc++.h> using namespac ...

  9. 邻接矩阵实现图的存储,DFS,BFS遍历

    图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...

随机推荐

  1. 中介者模式(c++实现)

    中介者模式 目录 中介者模式 模式定义 模式动机 UML类图 源码实现 优点 缺点 模式定义 中介者模式(Mediator),用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显示地相互引用, ...

  2. 写给程序员的机器学习入门 (八) - 卷积神经网络 (CNN) - 图片分类和验证码识别

    这一篇将会介绍卷积神经网络 (CNN),CNN 模型非常适合用来进行图片相关的学习,例如图片分类和验证码识别,也可以配合其他模型实现 OCR. 使用 Python 处理图片 在具体介绍 CNN 之前, ...

  3. 题解 洛谷 P4143 【采集矿石】

    对于一个固定的左端点,右端点向右移动时,其子串权值和不断增大,字典序降序排名不断减小,因此对于一个左端点,最多存在一个右端点使其满足条件. 所以可以枚举左端点,然后二分右端点的位置,权值和通过前缀和来 ...

  4. Linux下给PHP安装redis扩展

    一.下载redis扩展源码包 PHP官网下载地址:http://pecl.php.net/package/redis 二.安装依赖插件 yum -y install wget make gcc gcc ...

  5. Myeclipse-10.7.1版本破解

    自从上次写了IDEA2020版本破解方式,这次写一下Myeclipse10.7.1版本破解 下方链接是IDEA破解教程 点击即可跳转 Myeclipse下载地址这里我上传到了百度网盘    这里提取码 ...

  6. 《Python Web开发实战》|百度网盘免费下载|Python Web开发

    <Python Web开发实战>|百度网盘免费下载|Python Web开发 提取码:rnz4 内容简介 这本书涵盖了Web开发的方方面面,可以分为如下部分: 1. 使用最新的Flask ...

  7. 图解 JVM 核心知识点(面试版)

    一.基本概念 1.1 OpenJDK 自 1996 年 JDK 1.0 发布以来,Sun 公司在大版本上发行了 JDK 1.1.JDK 1.2.JDK 1.3.JDK 1.4.JDK 5,JDK 6 ...

  8. 算法数据结构 | 只要30行代码,实现快速匹配字符串的KMP算法

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法数据结构专题的第29篇文章,我们来聊一个新的字符串匹配算法--KMP. KMP这个名字不是视频播放器,更不是看毛片,它其实是由Kn ...

  9. matplotlib 显示中文问题

    import matplotlib.pyplot as plt plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签plt.rcParams[' ...

  10. Django学习路26_转换字符串大小写 upper,lower

    在 urls 中注册 url(r'getstr',views.getstr) 在 views.py 中添加函数 def getstr(request): string = 'abc' string_2 ...