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

广度优先搜索


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

从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;
}
运行结果如下:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

横版长图一键切割,短图制作高效又便捷!

在数字时代&#xff0c;图片处理已经成为了我们日常工作和生活中不可或缺的一部分。为了满足大家对于高效、便捷的图片处理需求&#xff0c;我们推出了一款全新的图片处理工具——横版长图一键切割&#xff01; 首先&#xff0c;我们进入首助编辑高手主页面&#xff0c;会看到…

优化改进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原理 …

Docker部署 SRS rtmp/flv流媒体服务器

一、介绍 SRS&#xff08;Simple Realtime Server&#xff09;是一款开源的流媒体服务器&#xff0c;具有高性能、高可靠性、高灵活性的特点&#xff0c;能够支持直播、点播、转码等多种流媒体应用场景。SRS 不仅提供了流媒体服务器&#xff0c;还提供了适用于多种平台的客户端…

Balking模式-实例

Balking模式 所谓Balk就是停止并返回的意思。 如果守护条件不成立&#xff0c;则立即中断处理。 因为Guarded Suspension模式是一直等待至可以运行。 当写入的内容与上次写入的内容完全相同时&#xff0c; 再向文件写入就显得多余了&#xff0c; 所以就不再执行写入操作。 也就…

深度解析Dubbo的基本应用与高级应用:负载均衡、服务超时、集群容错、服务降级、本地存根、本地伪装、参数回调等关键技术详解

负载均衡 官网地址&#xff1a; http://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/ 如果在消费端和服务端都配置了负载均衡策略&#xff0c; 以消费端为准。 这其中比较难理解的就是最少活跃调用数是如何进行统计的&#xff1f; 讲道理&#xff0c; 最少活跃数…

欧拉图及其应用

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

【Python学习】Python学习10-列表

目录 【Python学习】Python学习10-列表 前言创建语法访问列表中的值更新和删除列表元素操作列表列表截取Python列表函数&方法参考 文章所属专区 Python学习 前言 本章节主要说明Python的列表List。 创建语法 创建一个列表 通过方括号和逗号分割创建&#xff0c;列表数据…

Linux系统下gitee使用git提交代码

Linux系统下gitee使用git提交代码 一、安装配置git1.1 在 Linux 中安装 git&#xff0c;并生成授信证书1.2 将SSH key 添加到 ssh-agent1.2 将SSH key 添加到你的gitee账户 二、gitee 的使用2.1 下载项目到本地 三、上传gitee三步走3.1 三板斧第一招&#xff1a;git add3.2 三板…

FreeRTOS学习总结(二)FreeRTOS任务创建和删除API函数

实现动态创建任务流程 任务控制块结构体成员介绍 typedef struct tskTaskControlBlock {volatile StackType_t * pxTopOfStack; /* 任务栈栈顶&#xff0c;必须为TCB第一个成员 */ListItem_t xStateListItem; /* 任务状态列表项 */ Li…

解决:Unity : Error while downloading Asset Bundle: Couldn‘t move cache data 问题

目录 问题&#xff1a; 尝试 问题得到解决 我的解释 问题&#xff1a; 最近游戏要上线&#xff0c;发现一个现象&#xff0c;部分机型在启动的时候闪退或者黑屏&#xff0c;概率是5%左右&#xff0c;通过Bugly只有个别机型才有这个现象&#xff0c;其实真实情况比这严重的多…

池化层解析:简单易懂理解 PyTorch 中的核心组件

目录 torch.nn详解 nn.MaxPool1d nn.MaxPool2d nn.MaxPool3d nn.MaxUnpool1d nn.MaxUnpool2d nn.MaxUnpool3d nn.AvgPool1d nn.AvgPool2d nn.AvgPool3d nn.FractionalMaxPool2d nn.FractionalMaxPool3d nn.LPPool1d nn.LPPool2d nn.AdaptiveMaxPool1d nn.Adapt…

git打tag以及拉取tag

场景&#xff1a;某次git代码发布后定版记录&#xff0c;将发版所在的commit时候代码打上tag记录&#xff0c;方便后期切换到对应tag代码位置。 查看所有tag名 git tag// 1.1.0 // 1.0.0查看tag和描述 git tag -l -n//1.0.0 云监管一期项目完结 //1.1.0 …

练习-指针笔试题

目录 前言一、一维整型数组1.1 题目一1.2 题目二 二、二维整型数组2.1 题目一2.2 题目二2.3 题目三 三、结构体3.1 题目一&#xff08;32位机器运行&#xff09; 四、字符数组4.1 题目一4.2 题目二 总结 前言 本篇文章记录关于C语言指针笔试题的介绍。 一、一维整型数组 1.1 …

【GoLang入门教程】Go语言几种标准库介绍(五)

如何解决大模型的「幻觉」问题&#xff1f; 文章目录 如何解决大模型的「幻觉」问题&#xff1f;前言几种库image库 (常见图形格式的访问及生成)关键概念和类型&#xff1a;示例 IO库示例 math库(数学库)常用的函数和常量&#xff1a;示例 总结专栏集锦写在最后 前言 上一篇&a…

Spring Redis Client使用Hessian序列化HINCRBY命令的Bug

前言&#xff1a; 公司自己封装Redis Client架包&#xff0c;使用Hessian协议对Redis中Value值进行序列化。在使用Hash结构的HINCRBY命令&#xff0c;处理序列化异常的问题。下面&#xff0c;我将详细说明一下。 正文&#xff1a; 公司封装Redis Client架包&#xff0c;其实就…

开源大数据集群部署(三)集群mysql数据库部署

开源大数据集群部署&#xff08;一&#xff09;集群实施规划 开源大数据集群部署&#xff08;二&#xff09;集群基础环境实施准备 作者&#xff1a;櫰木 本文将介绍mysql部署&#xff0c;其中在hd1.dtstack.com主机root权限下安装配置 1 解压文件 解压名为mysql-8.0.31-lin…

Spring MVC(day1)

什么是MVC MVC是一种设计模式&#xff0c;将软件按照模型、视图、控制器来划分&#xff1a; M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为数据承载Bean&#xff1a;专门存储业务数据…

我在工作一年时怎么都看不懂的编程写法。今天手把手教给你

作为一名程序员&#xff0c;你一定遇到或亲自写过这样的代码。有人将它形象的形容为shi山&#xff0c;或者被戏称为“面向保就业编程”。 以下面这个代码为例&#xff0c;其中的问题也显而易见&#xff0c;当越来越多的条件判断时&#xff0c;代码会变得非常臃肿&#xff0c;难…

使用Pipeline和ColumnTransformer提升机器学习代码质量

机器学习项目中最冗长的步骤通常是数据清洗和预处理&#xff0c;Scikit-learn库中的Pipeline和 and ColumnTransformer通过一次封装替代逐步运行transformation步骤&#xff0c;从而减少冗余代码量。 1. Pipeline vs. ColumnTransformer 训练模型前&#xff0c;需要将数据集分…

目标检测数据集大全「包含VOC+COCO+YOLO三种格式+划分脚本+训练脚本」(持续原地更新)

一、作者介绍&#xff1a;五年算法开发经验、AI 算法经理、阿里云开发社区专家博主、稀土掘金人工智能内容评审委员会成员。擅长&#xff1a;检测、分割、理解、AIGC 等算法训练与部署。 二、数据集介绍&#xff1a; 质量高&#xff1a;高质量图片、高质量标注数据&#xff0c;…