数据结构与算法(十)深度优先搜索与广度优先搜索

广度优先搜索


广度优先搜索:从一个顶点出发(由开始时顶点创造顺序优先决定),访问所有没有被访问过的临节点。然后在从被访问过的节点出发,重复之前的操作
如下为一个图

从1出发,先后访问2 3,之后2访问它的邻接点4,3访问它的邻接点5(因为4已经被访问过了,所有节点只访问一次),最后4访问6,因为5的邻接点4 6访问过了,所以5不再访问6.
由该途径可以得到一个树,叫做广度优先生成树, 如下图所示

该存储路径由一个队列的形式和一个辅助数组存储该点是否被访问


1已经出队,所以数组1位置存储true,此时入队1的邻接点2 3,此后每出列一个邻接点,该邻接点的邻接点入列,数组相应的存储true,直到最后一个邻接点出列,算法结束

图有两种状态:连通和不连通,图中各顶点不一定要连接
所有节点都有连接叫做连通图,否则叫做不连通图
如下有两个图,同样可以当作一个图处理,也可以广度优先遍历

深度优先搜索


深度优先搜索:类似于黏菌走迷宫,先沿一条路走,无路可走时再回退
如下图:

首先从顶点1开始,走到2(可以能走3),然后走4,5,此时发现无路可走,退回4,发现4走过了,回到2,发现6没有走,就走6,然后回到2,回到1,1的右侧路同左侧路一致,3 7 8直到走完 
在以上路线中依然有相应的数组去辅助访问,true或者false
此路径仍然可以以一个树来进行表示,叫做深度优先生成树:

该存储路径可由一个栈的形式和一个辅助数组存储该点是否被访问,现不具体表示

广度优先搜索代码实现


具体代码需要包含头文件<queue> STL中方法
应用:
std::queue<int>Q; 声明一个队列
Q.push(12); 传入12 
std::cout << Q.front() << std::endl;打印队列首位元素
Q.pop(); 弹出队列首位
Q.empty(); 检查队列是否为空

代码实现:

需要包含的头文件如下

#include <iostream>
#include <queue>

const int g_MaxCount = 100; 顶点最大值
bool visited[g_MaxCount]; 访问标志数组

typedef struct 存储数据
{
    char Vex[g_MaxCount]; 顶点
    int Edge[g_MaxCount][g_MaxCount]; 边
    int VexCount; 顶点总数
    int EdgeCount; 边总数
}AMGraph;

int locatecex(AMGraph G, char x) 查找顶点下标
{
    for (size_t i = 0; i < G.VexCount; i++)
    {
        if (x == G.Vex[i])
        {
            return i;
        }
    }
    return -1; 如果没有找到返回-1
}

void Create(AMGraph & G) 创建一个有向图的邻接矩阵
{
    std::cout << "G.VexCount" << std::endl;
    std::cin >> G.VexCount; 输入顶点总数
    std::cout << "G.EdgeCount" << std::endl;
    std::cin >> G.EdgeCount; 输入边总数
    for (size_t i = 0; i < G.VexCount; i++)
    {
        std::cin >> G.Vex[i]; 存储顶点
    }
    for (size_t i = 0; i < G.VexCount; i++) 
    {
        for (size_t j = 0; j < G.VexCount; j++)
        {
            G.Edge[i][j] = 0; 邻接矩阵内容全部初始化为0
        }
    }
    char cStart; 
    char cEnd; 两个临时变量
    int nStartIndex; 
    int nEndIndex; 存储获取后的下标

    while (G.EdgeCount--) 
    {
        std::cin >> cStart >> cEnd;
        nStartIndex = locatecex(G, cStart); 
        nEndIndex = locatecex(G, cEnd);
        if (nStartIndex != -1 && nEndIndex != -1)
        {
            //G.Edge[nStartIndex][nEndIndex] = G.Edge[nEndIndex][nStartIndex] = 1;无向图情况
            G.Edge[nStartIndex][nEndIndex] = 1;有向图情况
        }
        else
        {
            G.EdgeCount++; 输入错误的情况下,让该循坏的参数再次加1回到之前状态
        }
    }

}

void BFS(AMGraph G, int nIndex) 遍历 传入图和下标
{
    int QHeadValue; 一临时变量
    std::queue<int>Q; 使用队列
    visited[nIndex] = true; 表示当前顶点已经被访问
    Q.push(nIndex); 使数组相应位置元素加入队列
    while (!Q.empty()) 队列不空的情况下
    {
        QHeadValue = Q.front(); 存储元素的值
        Q.pop(); 弹出队列该值
        for (size_t i = 0; i < G.VexCount; i++)
        {
            if (G.Edge[QHeadValue][i] && !visited[i]) 
            {
                std::cout << G.Vex[i] << "\t"; 输出传入图下标
                visited[i] = true;
                Q.push(i); 传入队列中
            }
        }
    }
}

void print(AMGraph G) 遍历输出该图
{
    for (size_t i = 0; i < G.VexCount; i++)
    {
        for (size_t j = 0; j < G.VexCount; j++)
        {
            std::cout << G.Edge[i][j] << "\t";
        }
        std::cout << std::endl;
    }
}

int main()
{
    char szBuffer;
    AMGraph G;
    Create(G);
    print(G);
    std::cout << "input start node:" << std::endl;
    std::cin >> szBuffer; 输入遍历图的起点
    int nIndex = locatecex(G, szBuffer); 接受该起点获取下标
    if (nIndex != -1)
    {
        BFS(G, nIndex);
    }
    system("pause");
    return 0;
}
运行结果如下:包括遍历结果和邻接矩阵


深度优先搜索代码实现


具体代码实现同广度大致相同
需要包含的头文件如下

#include <iostream>
#include <queue>

const int g_MaxCount = 100;//顶点最大值
bool visited[g_MaxCount];//访问标志数组

typedef struct {
    char Vex[g_MaxCount];
    int Edge[g_MaxCount][g_MaxCount];
    int VexCount;
    int EdgeCount;
}AMGraph;

int locatecex(AMGraph G, char x)
{
    for (size_t i = 0; i < G.VexCount; i++)
    {
        if (x == G.Vex[i])
        {
            return i;
        }
    }
    return -1;
}

void Create(AMGraph & G)
{
    std::cout << "G.VexCount" << std::endl;
    std::cin >> G.VexCount;
    std::cout << "G.EdgeCount" << std::endl;
    std::cin >> G.EdgeCount;
    for (size_t i = 0; i < G.VexCount; i++)
    {
        std::cin >> G.Vex[i];
    }
    for (size_t i = 0; i < G.VexCount; i++)
    {
        for (size_t j = 0; j < G.VexCount; j++)
        {
            邻接矩阵内容全部初始化为0
            G.Edge[i][j] = 0;
        }
    }
    char cStart;
    char cEnd;
    int nStartIndex;
    int nEndIndex;

    while (G.EdgeCount--)
    {
        std::cin >> cStart >> cEnd;
        nStartIndex = locatecex(G, cStart);
        nEndIndex = locatecex(G, cEnd);
        if (nStartIndex != -1 && nEndIndex != -1)
        {
            //G.Edge[nStartIndex][nEndIndex] = G.Edge[nEndIndex][nStartIndex] = 1;
            G.Edge[nStartIndex][nEndIndex] = 1;
        }
        else
        {
            G.EdgeCount++;
        }
    }

}

void DFS(AMGraph G, int nIndex) 算法同广度有所修改
{
    std::cout << G.Vex[nIndex] << "\t"; 打印当前节点
    visited[nIndex] = true;
    for (size_t i = 0; i < G.VexCount; i++)
    {
        if (G.Edge[nIndex][i] && !visited[i])
        {
            DFS(G, i); 递归
        }
    }
}

void print(AMGraph G)
{
    for (size_t i = 0; i < G.VexCount; i++)
    {
        for (size_t j = 0; j < G.VexCount; j++)
        {
            std::cout << G.Edge[i][j] << "\t";
        }
        std::cout << std::endl;
    }
}

int main()
{
    char szBuffer;
    AMGraph G;
    Create(G);
    print(G);

    std::cout << "input start node:" << std::endl;
    std::cin >> szBuffer;
    int nIndex = locatecex(G, szBuffer);
    if (nIndex != -1)
    {
        DFS(G, nIndex);
    }
    system("pause");
    return 0;
}
运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/305762.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VMware复制粘贴共享文件夹

win和虚拟机之间&#xff0c;无法复制粘贴&#xff0c;共享文件夹的解决方案。 安装VMware tools 1&#xff0c;先检查虚拟机设置部分。共享文件夹已启用。复制粘贴已启用。 2&#xff0c;安装tools.选择重新安装VMware tools. (此图片为安装过的截图) 成功后会显示如图。…

C++的一些书籍整理(个人学习)

UNIX环境高级编程&#xff08;第三版&#xff09; UNXI网络编程卷1 网络编程的笔记 收藏 我会了 一堆书 这个仓 数据库连接池原理介绍常用连接池介绍

计算机体系结构期末复习流程大纲

1.存储器和cache 存储器的容量、速度与价格之间的要求是相互矛盾的&#xff0c;速度越快&#xff0c;没bit位价格越高&#xff0c;容量越大&#xff0c;速度越慢&#xff0c;目前主存一般有DRAM构成。 处理器CPU访问存储器的指标&#xff1a; 延迟时间&#xff08;Latency&am…

LeetCode刷题--- 下降路径最小和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述动…

Oracle文件自动“减肥”记

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

欧拉图及其应用

什么是欧拉图 提到欧拉图就要谈到哥尼斯堡七桥问题&#xff0c;最初有这样的一个问题的&#xff1a;18世纪中叶&#xff0c;东普鲁士哥尼斯堡城有一条贯穿全城的普雷格尔河&#xff0c;河中有两个岛&#xff0c;通过七座桥彼此相连&#xff0c;如下图所示 问题是这样的&…

UnitTestreport之UnitTest用例失败重运行机制

前言 很多小伙伴一直在诟病unittest&#xff0c;说unittest相对pytest来说太鸡肋了&#xff0c;pytest中提供了很多高级功能unittest中都没有。在这里还是想为unittest打抱不平一下&#xff0c;unittest是由python官方维护的官方库&#xff0c;官方库都是比较轻量级的&#xf…

以太坊开发者会议回顾:坎昆升级、硬分叉与布拉格

作者&#xff1a;Christine Kim Galaxy研究副总裁 编译&#xff1a;秦晋 碳链价值 2024年1月4日&#xff0c;以太坊开发人员齐聚Zoom for All Core Developers Execution (ACDE) Call #178 上。ACDE电话会议通常由以太坊基金会协议负责人Tim Beiko主持&#xff0c;是一个开发人…

【STM32】STM32学习笔记-串口发送和接收(27)

00. 目录 文章目录 00. 目录01. 串口简介02. 串口相关API2.1 USART_Init2.2 USART_InitTypeDef2.3 USART_Cmd2.4 USART_SendData2.5 USART_ReceiveData 03. 串口发送接线图04. USB转串口模块05. 串口发送程序示例06. 串口发送支持printf07. 串口发送支持printf_v208. 串口发送和…

5分钟彻底搞懂什么是token

大家好啊&#xff0c;我是董董灿。 几年前在一次工作中&#xff0c;第一次接触到自然语言处理模型 BERT。 当时在评估这个模型的性能时&#xff0c;领导说这个模型的性能需要达到了 200 token 每秒&#xff0c;虽然知道这是一个性能指标&#xff0c;但是对 token 这个概念却不…

聚道云软件连接器助力某餐饮管理有限公司实现人力资源信息自动化

客户介绍&#xff1a; 某餐饮管理有限公司是一家集餐饮连锁、餐饮管理、餐饮咨询等业务于一体的综合性餐饮企业。公司业务遍布全国多个城市&#xff0c;拥有众多员工。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 客户痛点&#xff1a; 员工入离职…

怎样把照片不想要的部分涂抹掉?安利下面这三款软件给你

在元旦假期的旅行中&#xff0c;我带着相机&#xff0c;用镜头记录下了每一个美好时刻。我爬上了高山之巅&#xff0c;俯瞰群山连绵起伏&#xff1b;我漫步在海滩上&#xff0c;感受海风轻拂脸颊&#xff1b;我甚至在城市的角落里&#xff0c;发现了那些平日里未曾留意的小确幸…

Unity 踩坑记录 AnyState 切换动画执行两次

AnySate 切换动画 Can Transition To Self 将这个勾选去掉&#xff01;&#xff01;&#xff01;

树定义及遍历

1、定义树 可以参考链表&#xff0c;链表遍历不方便&#xff0c;如果单链表有多个next指针&#xff0c;则就形成了树。 Java: public class TreeNode {int val;TreeNode left, right;TreeNode(int val) { this.val val; this.left null;this.right null;} } Python&#…

【上海】买套二手房需要多少钱?

上次我们看了苏州的二手房&#xff0c;这次我们一起来看下上海的二手房价格如何。 数据来源 数据来自贝壳二手房&#xff0c;每个区最多获取了3千条房源信息&#xff0c;数据共计4万条左右 对数据感兴趣的朋友&#xff0c;公众号后台发送上海二手房获取数据文件 各区房源单价…

Linux中快速搭建RocketMQ测试环境

必要的文件下载 为什么选择RocketMQ | RocketMQ x86_64位JDK下载0jdk/8u391-b13 rocketmq二进制包下载-rocketmq-all-5.1.4-bin-release.zip 编译好的直接可用的dashboard【rocketmq-dashboard-1.0.0.jar】请在文章顶部下载 dashboard配套的配置文件【application.propert…

shell解释和权限概念

shell问题解释 问题1&#xff1a; 为什么要使用shell外壳&#xff1f; 因为用户不能直接访问操作系统 问题2&#xff1a; shell外壳是什么&#xff1f; shell外壳的工作是将使用者的命令翻译给核心&#xff08;kernel&#xff09;处理。 同时将处理结果反馈给使用者。 问…

mysql之导入导出远程备份

文章目录 一、navicat导入导出二、mysqldump命令导入导出2.1导出2.1.1 导出表数据和表结构2.1.2 只导出表结构() 2.2 导入(使用mysqldump导入 包含t _log表的整个数据库 共耗时 20s;)方法一&#xff1a;方法二&#xff1a; 三、LOAD DATA INFILE命令导入导出(只针对单表)设置导…

Linux编译器

目录 Linux编译器 程序编译的步骤 gcc编译器完成C语言程序的编译 预处理 编译 汇编 链接 上一期我们学习了Linux中的vim编辑器&#xff0c;其实本质上vim编辑器就是写代码的一个工具。上期内容我们也已经说过&#xff0c;一份合格的代码需要进行编写&#xff0c;编译&am…

优化改进YOLOv8算法之AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv

目录 1 AKConv原理 1.1 Define the initial sampling position 1.2 Alterable convolutional operation 1.3 Extended AKConv 2 YOLOv8中加入AKConv模块 2.1 AKConv.py文件配置 2.2 task.py配置 2.3 创建添加优化点模块的yolov8-AKConv.yaml 2.4 训练 1 AKConv原理 …