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

news2024/11/14 15:12:52

广度优先搜索


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

从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.coloradmin.cn/o/1369749.html

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

相关文章

String的(toCharArray\split)方法*

题目 class Solution {public int firstUniqChar(String s) {int[] sum new int[26];char[] num s.toCharArray();for(int i0;i<num.length;i) {sum[num[i]-a];}for(int j0;j<num.length;j) {if(sum[num[j]-a] 1) {return j;}}return -1; } }题目 …

我的1827创作纪念日

机缘 习惯性早上打开电脑&#xff0c;看看CSDN上的资讯&#xff0c;了解行业动态、当前新的技术和大佬的分享。自己动手写应该是2019 年 01 月 08 日&#xff0c;当时应该是在用安装和使用Oracle&#xff0c;遇到一些问题&#xff0c;写下第一篇博客 Oracle存储过程常见问题及…

【RK3399 PCIE调试——硬件信息资源获取】

一、1、 硬件接口 二、2、 PCB原理图 三、 官网地址&#xff1a; https://t.rock-chips.com/portal.php 相关资料和固件烧写可参考资料下载菜单

欧拉图及其应用

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

(非常全面的干货)Python接口自动化测试框架实战开发

一丶叙述 1.项目介绍 整个项目分为四个部分&#xff1a;接口基础丶接口开发丶Unittest与接口测试结合以及接口自动化框架从设计到开发 接口基础包括&#xff1a;HTTP接口 / 常见接口 / 接口工具 / 接口基础知识 接口开发&#xff1a;通过Django来开发get/post接口 Unittes…

“器官短缺”将被打破 基因编辑猪成为人类的“二师兄”

器官移植被称为生命之灯。但是&#xff0c;受制于传统观念及对人体器官捐献意义的不了解&#xff0c;人体器官捐献的数量&#xff0c;还远远达不到需求。目前&#xff0c;全国有近30万的患者在等待器官移植&#xff0c;但每年只有近一万的患者能真正得到器官移植&#xff0c;缺…

银联扫码第三方支付接口申请:开启便捷支付新时代

随着移动支付的普及&#xff0c;越来越多的商家开始接受微信、支付宝等第三方支付平台的付款方式。然而&#xff0c;作为国内最大的银行卡组织&#xff0c;银联也在不断拓展其业务范围&#xff0c;推出了自己的扫码支付接口。本文将为您详细介绍银联扫码第三方支付接口的申请流…

【Azure 架构师学习笔记】- Azure Databricks (5) - Unity Catalog 简介

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (4) - 使用Azure Key Vault 管理ADB Secret 前言 DataBricks Unity Catalog&#xff08;UC&#xff09;是一个统一的对数据资产治理的解决方案…

【算法Hot100系列】有效的数独

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

GPS 模拟器

GPS 工具包&#xff1a;https://www.ni.com/es/support/downloads/software-products/download.gnss-test-toolkit.html#333303 GPS-SDR-SIM&#xff1a;https://github.com/osqzss/gps-sdr-sim GPS LabVIEW &#xff1a;http://mikioblog.dolphinsystem.jp/2017/08/gps-sdr-si…

FastApi-快速入门1

FastAPI 是一个用于构建 API 的现代、快速&#xff08;高性能&#xff09;的 web 框架&#xff0c;使用 Python 3.8 并基于标准的 Python 类型提示。 关键特性: 快速&#xff1a;可与 NodeJS 和 Go 并肩的极高性能&#xff08;归功于 Starlette 和 Pydantic&#xff09;。最快…

Exception sending a multicast message:Network is unreachable故障

出现这个故障就是没有连接到网络&#xff0c;如果虚拟机没有连接到本机&#xff0c;那么就会出现这个情况&#xff0c;当虚拟机连接到本机就会自动消失&#xff0c;同时如果是用电脑直接安装Ubuntu运行也会出现这个情况&#xff0c;应该是要连接到一个路由器里面这个情况才会消…

Java面向对象综合练习(拼图小游戏),用java图形化界面实现拼图小游戏

1. 设计游戏的目的 锻炼逻辑思维能力利用Java的图形化界面&#xff0c;写一个项目&#xff0c;知道前面学习的知识点在实际开发中的应用场景 2. 游戏的最终效果呈现 Hello&#xff0c;各位同学大家好。今天&#xff0c;我们要写一个非常有意思的小游戏 —《拼图小游戏》 我们…

Filter Options in Select Field

Filter Options in Select Field 假设有两个下拉字段State和City。邦有两个值卡纳塔克邦和马哈拉施特拉邦&#xff0c;城市有四个值&#xff0c;班加罗尔&#xff0c;迈索尔&#xff0c;孟买和浦那。如果希望根据State中选择的值过滤City中的选项&#xff0c;可以编写如下所示的…

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出

EtherCAT主站SOEM -- 13 --Qt-Soem通过界面按键控制 EtherCAT IO模块的io输出 一 mainwindow.c 文件函数:1.1 自定义PDO配置2.2 主站初始化2.3 去motrorcontrol界面二 motrorcontrol.c 文件三 allvalue.h 文件该文档修改记录:总结一 mainwindow.c 文件函数: mainwindow主界…

JavaScript高级程序设计读书记录(六):定型数组,Map

1. 定型数组 定型数组&#xff08;typed array&#xff09;是 ECMAScript 新增的结构&#xff0c;目的是提升向原生库传输数据的效率。实际上&#xff0c;JavaScript 并没有“TypedArray”类型&#xff0c;它所指的其实是一种特殊的包含数值类型的数组。 1.1 历史 随着浏览器…

【实用技巧】Windows 电脑向iPhone或iPad传输视频方法1:无线传输

一、内容简介 本文介绍如何使用 Windows 电脑向 iPhone 或 iPad 传输视频&#xff0c;以 iPhone 为例&#xff0c;iPad的操作方法类似&#xff0c;本文不作赘述。 二、所需原材料 Windows 电脑&#xff08;桌面或其它文件夹中存有要导入的视频&#xff09;、iPhone 14。 待…

浅析ARMv8体系结构:A64指令集

文章目录 A64指令编码格式加载与存储指令寻址模式变基模式前变基模式后变基模式 PC相对地址模式 伪指令加载与存储指令的变种不同位宽的加载与存储指令多字节内存加载和存储指令基地址偏移量模式前变基模式后变基模式 跳转指令返回指令比较并跳转指令 其它指令内存独占访问指令…

基于YOLOv8 + BotSORT实现球员和足球检测与跟踪 (步骤 + 源码)

导 读 本文主要介绍基于YOLOv8和BotSORT实现球员和足球检测与跟踪 &#xff0c;并给出步骤和代码。 背景介绍 本文旨在了解 YOLO 架构并在自定义数据集上对其进行训练&#xff0c;然后微调模型以获得更好的结果&#xff0c;并运行推理以了解最有效的方法。 什么是YOLO&#x…

2024年1月10日 十二生肖 今日运势

小运播报&#xff1a;2024年1月10日&#xff0c;星期三&#xff0c;农历十一月廿九 &#xff08;癸卯年乙丑月癸酉日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;龙、牛、蛇 需要注意&#xff1a;鸡、狗、兔 喜神方位&#xff1a;东南方 财神方位&#xff1…