图的遍历方法——DFS和BFS

2023-11-05

DFS类似于树的先序遍历,因此可以用递归实现;

BFS类似于树的层次遍历,因此可以用队列实现。

说明:下面代码中图的存储方式是邻接表。关于邻接表和邻接矩阵可看邻接表和邻接矩阵

1.深度优先遍历( Depth First Search)

思想

从图中的某一个顶点 v0 出发,访问此顶点,然后依次从 v0 的没被访问的邻接点出发深度优先遍历图(体现了递归的思想),直至图中所有和 v0 有路径相通的顶点都被访问到;若此时图中仍有结点没有被访问,则另选图中一个未曾访问的顶点作起始点,重复上述过程。

因为要判断某顶点是否被访问过,所以需要一visit[]数组来记录,若访问过则为true,没访问过则为false

例子

在这里插入图片描述
遍历结果: V1–> V2 --> V4 -->V8 --> V5 --> V3 --> V6 --> V7

代码

#include <iostream>
#define MAX_VEX_NUM 20
using namespace std;
typedef char NumType;

struct EdgeNode
{
    int adjvex;
    EdgeNode *nextedge;
};
struct VexNode
{
    NumType data;
    EdgeNode *firstedgd;
};
struct Graph
{
    VexNode Vex[MAX_VEX_NUM];
    int VexNum;
    int EdgeNum;
};
int Locate(Graph G,NumType v)
{
    int i;
    for(i=0;i<G.VexNum;i++)
        if(G.Vex[i].data==v)return i;
    return -1;
}
void CreateGraph(Graph &G)
{
    cout<<"请输入结点个数和边的条数:";
    cin>>G.VexNum;cin>>G.EdgeNum;
    int i,j,k;
    cout<<"请输入结点信息:";
    for(i=0;i<G.VexNum;i++){cin>>G.Vex[i].data;G.Vex[i].firstedgd=0;}
    NumType v1,v2;
    for(k=0;k<G.EdgeNum;k++)
    {
        cin>>v1;cin>>v2;
        i=Locate(G,v1);j=Locate(G,v2);
        EdgeNode *p=new EdgeNode();
        EdgeNode *p0=new EdgeNode();
        *p={j,G.Vex[i].firstedgd};
        G.Vex[i].firstedgd=p;
        //这是无向图才有的
        *p0={i,G.Vex[j].firstedgd};
        G.Vex[j].firstedgd=p0;
    }
}

//上面的代码是用邻接表存储图结构的过程
//只有下面的代码才是DFS
bool Visited[MAX_VEX_NUM]={false};
void DFS(Graph G,int v)//从下标为v的顶点开始
{
    Visited[v]=true;
    cout<<G.Vex[v].data<<" ";
    EdgeNode *p=0;
    for(p=G.Vex[v].firstedgd;p!=0;p=p->nextedge)
        if(!Visited[p->adjvex])DFS(G,p->adjvex);
}
void DFSTraverse(Graph G)
{
    int i;
    for(i=0;i<G.VexNum;i++)
        if(!Visited[i])DFS(G,i);
}
int main()
{
    Graph G;
    CreateGraph(G);
    DFSTraverse(G);
    return 0;
}

2.宽度优先遍历( Breadth First Search)

思想

从图中的某一个顶点 v0 出发,访问v0之后,依次访问v0 的没被访问的邻接点,然后,再分别从这些邻接点出发,广度优先遍历图,直至所有顶点都被访问;若此时图中仍有结点没有被访问,则另选图中一个未曾访问的顶点作起始点,重复上述过程。

1、可以看出BFS类似于树的层次遍历,所以需要队列来存储顶点;
2、因为要判断某顶点是否被访问过,所以需要一visit[]数组来记录,若访问过则为true,没访问过则为false。

例子

在这里插入图片描述
遍历结果: V1–> V2 --> V3 -->V4 --> V5 --> V6 --> V7 --> V8

代码

#include <iostream>
#define MAX_VEX_NUM 20
#include <queue>
using namespace std;
typedef char NumType;
struct EdgeNode
{
    int adjvex;
    EdgeNode *nextedge;
};
struct VexNode
{
    NumType data;
    EdgeNode *firstedgd;
};
struct Graph
{
    VexNode Vex[MAX_VEX_NUM];
    int VexNum;
    int EdgeNum;
};
int Locate(Graph G,NumType v)
{
    int i;
    for(i=0;i<G.VexNum;i++)
        if(G.Vex[i].data==v)return i;
    return -1;
}
void CreateGraph(Graph &G)
{
    cout<<"请输入结点个数和边的条数:";
    cin>>G.VexNum;cin>>G.EdgeNum;
    int i,j,k;
    cout<<"请输入结点信息:";
    for(i=0;i<G.VexNum;i++){cin>>G.Vex[i].data;G.Vex[i].firstedgd=0;}
    NumType v1,v2;
    cout<<"请输入边的信息:";
    for(k=0;k<G.EdgeNum;k++)
    {
        cin>>v1;cin>>v2;
        i=Locate(G,v1);j=Locate(G,v2);
        EdgeNode *p=new EdgeNode();
        EdgeNode *p0=new EdgeNode();
        *p={j,G.Vex[i].firstedgd};
        G.Vex[i].firstedgd=p;
        //这是无向图才有的
        *p0={i,G.Vex[j].firstedgd};
        G.Vex[j].firstedgd=p0;
    }
}

//上面的代码是用邻接表存储图结构的过程
//只有下面的代码才是BFS
bool Visited[MAX_VEX_NUM]={false};
void BFS(Graph G)
{
    queue<int> q;
    EdgeNode *p=0;
    int i;
    for(i=0;i<G.VexNum;i++)
    {
        if(!Visited[i])
        {
            Visited[i]=true;
            q.push(i);
            while(!q.empty())
            {
                int t=q.front();
                q.pop();
                cout<<G.Vex[t].data<<" ";
                for(p=G.Vex[t].firstedgd;p!=0;p=p->nextedge)
                {
                    if(!Visited[p->adjvex])
                    {
                        Visited[p->adjvex]=true;
                        q.push(p->adjvex);
                    }
                }
            }
        }
    }
}
int main()
{
    Graph G;
    CreateGraph(G);
    BFS(G);
    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图的遍历方法——DFS和BFS 的相关文章

随机推荐

  • 【Tableau小练习】销售数据的分析思路

    概要 电商数据分析案例 分析思路 从整体到局部 关键指标 销售额 通过宏观的数据 找出最明显的数据趋势 结合品牌自身的营销活动 再下钻挖掘详细的价值信息 成果展示 Tableau Public https public tableau co
  • 17_Nginx_PostRead阶段

    文章目录 post read 阶段 获取真实的用户IP地址 基于变量使用用户ip realip 模块 realip 模块的指令 post read 阶段 获取真实的用户IP地址 tcp 四元组 src ip src port dst ip
  • 本地镜像如何推送到docker 仓库

    要将本地镜像推送到Docker仓库 需要按照以下步骤操作 1 首先 使用 docker login 命令登录到Docker仓库 输入用户名和密码进行身份验证 2 然后 使用 docker tag 命令为本地镜像添加标签 语法为 docker
  • 39_MoreThanHalfNumber 数组中超过一半的元素

    数组中有一个数字出现的次数超过数组长度的一半 请找出这个数字 你可以假设数组是非空的 并且给定的数组总是存在多数元素 示例 1 输入 1 2 3 2 2 2 5 4 2 输出 2 1 利用hashmap统计数组中元素出现的次数 如果次数大于
  • Elasticsearch 搜索数组字段

    我的个人博客 逐步前行STEP 1 搜索 数组字段 tags 中同时存在元素 str a str b query bool filter term tags str a term tags str b 2 搜索 数组字段 tags 中存在元
  • vue怎么vw布局好用_vue2.x使用响应式vw布局(px自动转为vw)

    浏览器支持一览 1 依赖包引入 yarn add postcss px to viewport opt postcss viewport units cssnano cssnano preset advanced dev 2 更改项目根目录
  • [519]matplotlib(三)

    带误差线的条形图 import matplotlib pyplot as plt 输入数据 mean values 1 2 3 variance 0 2 0 4 0 5 bar labels bar 1 bar 2 bar 3 绘制图形 x
  • python3刷leetcode第165题165.compare version number

    class Solution def compareVersion self version1 str version2 str gt int version1 version1 split version2 version2 split
  • 入门ResNet,在Cub200数据集上复现Resnet50

    1 背景问题 1 如果只是单纯地把卷积层和池化层进行堆叠 造成的问题就会有梯度消失和梯度爆炸 梯度消失是指当在某一层进行BP的时候 误差为一个小于零的数 那不断相乘 就会趋近于零 梯度爆炸则是指某一层的开始误差都是大于1的数 直接相乘就会导
  • centos7 sh 注释_shell 中的单行注释和多行注释

    导读 关于 shell 中的单行注释和多行注释的问题 本文档介绍两种实用的方法 1 单行注释 众所周知 比如想要注释 echo Hello World root Jaking vim test sh echo Hello World 2 多
  • 如何进行需求测试/需求评审

    由于软件系统的复杂性 在需求分析阶段可能存在着开发方对委托方业务需求理解不全面 不准确的情况 在这种情况下 如果不进行相关的质量控制 往往会造成开发结果与用户需求不一致的后果 需求测试的目的就在于保证软件设计最大可能地满足有关用户的所有需求
  • 从前端传来的JSON中获取数据

    首先推荐一个神器 JSON在线解析及格式化验证 JSON cn 里面的 JSON在线解析 和 JSON生成JAVA实体 两个功能 前几天可是帮了我大忙了 前几天写一个功能 在这个功能中前端传过来的JSON十分复杂 示例如 Dispositi
  • virtualbox 安装centos7之后无法ssh登陆

    文章目录 virtualbox 安装 centos7 开启centos7网络 sshd 服务是否开启 设置 virtualbox 端口转发功能 设置secureCrt 连接参数 virtualbox 安装 centos7 virtualbo
  • 贝叶斯网络与R语言

    贝叶斯网络与R语言 基本语句 1 1网络的创建 加载扩展包和bnlearn包自带数据集marks 数据集marks 88 学生5门课的成绩 MECH mechanics VECT vectors ALG algebra ANL analys
  • 十一. Kubernetes 容器 container 设置详解

    目录 一 基础解释 yaml设置容器拉取镜像注意点 1 containers image 镜像 2 containers imagePullPolicy 镜像拉取策略 3 配置拉取私库镜像 spec下的imagePullSecrets 4
  • 【六级单词】

    affordable 价格合理的 cash 现金 insurance 保险 forune 一大笔钱 机会 运气 misfortune 不幸 灾难 luxury 奢侈 豪华 luxurious shop pension 养老金 抚恤金 com
  • C语言每日一题:16:数对。

    思路一 基本思路 1 x y均不大于n 就是小于等于n 2 x y大于等于k 3 一般的思路使用双for循环去遍历每一对数 代码实现 include
  • pytorch霹雳巴拉——图像分类篇

    up给的教程路线 图像分类 目标检测 一步步学习用pytorch实现深度学习在cv上的应用 并做笔记整理和总结 参考内容来自 up主的b站链接 https space bilibili com 18161609 channel index
  • layui 动态加载 select

    感谢小张帅三代以及他的好文 layui ajax select 动态添加数据方法 给我指明了前进的方向 首先 这是一个学习的过程 并不是最优方案 只是 玩索而有得 而己 做了一个联动的搜索框 本来一开始想用layuiselect第三方插件
  • 图的遍历方法——DFS和BFS

    DFS类似于树的先序遍历 因此可以用递归实现 BFS类似于树的层次遍历 因此可以用队列实现 说明 下面代码中图的存储方式是邻接表 关于邻接表和邻接矩阵可看邻接表和邻接矩阵 1 深度优先遍历 Depth First Search 思想 从图中