图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

news2025/9/20 19:07:06

一、图的遍历的定义:

从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次。(连通图与非连通图)

二、深度优先遍历(DFS);

1、访问指定的起始顶点;

2、若当前访问的顶点的邻接顶点有未被访问的,则任选一个访问之;反之,退回到最近访问过的顶点;直到与起始顶点相通的全部顶点都访问完毕;

3、若此时图中尚有顶点未被访问,则再选其中一个顶点作为起始顶点并访问之,转 2; 反之,遍历结束。

连通图的深度优先遍历类似于树的先根遍历

1、如何判别V的邻接点是否被访问?

解决办法:为每个顶点设立一个“访问标志”。首先将图中每个顶点的访问标志设为 FALSE,  之后搜索图中每个顶点,如果未被访问,则以该顶点为起始点,进行深度

优先遍历,否则继续检查下一顶点。

访问指定的起始顶点;若当前访问的顶点的邻接顶点有未被访问的,则任选一个访问之;

反之,退回到最近访问过的顶点;直到与起始顶点相通的全部顶点都访问完毕;

回退到1,发现了新的没有被访问的结点

继续回退,回退到0

再也找不到新的结点了,那么回退,回退到起始顶点,结束搜索

顶点的访问序列为:    v0 , v1 , v4 , v5 , v6 , v2 , v3(不唯一)

2、实现过程:依靠栈,一维数组和图的邻接矩阵存储方式

图的邻接矩阵存储方式

使用一个一维数组存储所有的顶点,对应的下标的元素为1(代表已经被访问),0(代表没有被访问)

先访问 v1,0进栈,0处置为1

继续访问 v2,1进栈,1处置为1

继续访问v4(依据邻接矩阵),3入栈,3处置为1

继续访问 v8,7入栈,7处置为1

继续访问 v5,4入栈,4处置为1

继续访问,发现没有还没访问的结点了,那么好,退栈(也就是回退)开始,回退到 v1处,也就是0的时候,发现了没有被访问的结点,那么继续访问之

继续访问 v3,2进栈,2处置为1,继续访问v6,5进栈,5处置为1,继续访问v7,6进栈,6处置为1

发现没有还没被访问的结点了,那么好,继续回退(也就是退栈的过程)

一直到栈空,说明深度优先搜索完毕。结束程序。

遍历图的过程实质上是对每个顶点查找其邻接点的过程,所耗费的时间取决于所采用的存储结构。

对图中的每个顶点至多调用1次DFS算法,因为一旦某个顶点已访问过,则不再从它出发进行搜索。

邻接链表表示:查找每个顶点的邻接点所需时间为O(e),e为边(弧)数,算法时间复杂度为O(n+e)。

数组表示:查找每个顶点的邻接点所需时间为O(n2),n为顶点数,算法时间复杂度为O(n2)。

3、代码实现

//访问标志数组

int visited[MAX] = {0};

//用邻接表方式实现深度优先搜索(递归方式)

//v 传入的是第一个需要访问的顶点

void DFS(MGraph G, int v)

{

        //图的顶点的搜索指针

        ArcNode *p;

        //置已访问标记

        visited[v] = 1;

        //输出被访问顶点的编号

        printf("%d ", v);

        //p指向顶点v的第一条弧的弧头结点

        p = G.vertices[v].firstarc;

        while (p != NULL)

        {

                //若p->adjvex顶点未访问,递归访问它

                if (visited[p->adjvex] == 0)

                {

                        DFS(G, p->adjvex);

                }

                //p指向顶点v的下一条弧的弧头结点

                p = p->nextarc;

        }

}

二、度优先搜索(BFS)

方法:从图的某一结点出发,首先依次访问该结点的所有邻接顶点 Vi1, Vi2, …, Vin 再按这些顶点被访问的先后次序依次访问与它们相邻接的所有未被访问的顶点,重复此过程,直至所有顶点均被访问为止。

顶点的访问次序

1、实现过程:依靠队列和一维数组来实现

2、代码实现

#include <iostream>

#include<queue>

using namespace std;

const int MAX = 10; 

//辅助队列的初始化,置空的辅助队列Q,类似二叉树的层序遍历过程 

queue<int> q;

//访问标记数组

bool visited[MAX]; 

//图的广度优先搜索算法

void BFSTraverse(Graph G, void (*visit)(int v)) 

{

        int v = 0; 

        //初始化访问标记的数组

        for (v = 0; v < G.vexnum; v++) 

        {

                visited[v] = false;

        }

        //依次遍历整个图的结点

        for (v = 0; v < G.vexnum; v++)

        {

                //如果v尚未访问,则访问 v

                if (!visited[v])

                {

                        //把 v 顶点对应的数组下标处的元素置为真,代表已经访问了

                        visited[v] = true;

                        //然后v入队列,利用了队列的先进先出的性质

                        q.push(v);

                        //访问 v,打印处理

                        cout << q.back() << " ";

                        //队不为空时

                        while (!q.empty())

                        {

                                //队头元素出队,并把这个出队的元素置为 u,类似层序遍历

                                Graph *u = q.front();

                                q.pop();

                                //w为u的邻接顶点

                                for (int w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G,u,w))

                                {

                                        //w为u的尚未访问的邻接顶点

                                        if (!visited[w])

                                        {

                                                visited[w] = true;

                                                //然后 w 入队列,利用了队列的先进先出的性质

                                                q.push(w);

                                                //访问 w,打印处理

                                                cout << q.back() << " ";

                                        }//end of if

                                }//end of for

                        }//end of while

                }//end of if

        }// end of for

}

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

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

相关文章

SoapUI 怎么下载:实用指南

SoapUI Windows 版本下载 今天带大家过一遍 SoapUI 在 Windows 系统下的安装教程吧&#xff01;各位 开发小伙伴 们可以跟着我一起来~ 下载安装包 下载链接&#xff1a;www.soapui.org/downloads/s… 安装 安装非常简单&#xff0c;只需双击它即可启动&#xff0c;安装程序…

CSS效果(工作中常用)

1、css文字溢出省略号 overflow: hidden; // 溢出隐藏 text-overflow: ellipsis; // 溢出用省略号显示 white-space: nowrap; // 规定段落中的文本不进行换行 overflow: hidden; // 溢出隐藏 text-overflow: ellipsis; // 溢出用省略…

深入了解Python中的进程控制和监控技巧,提高系统稳定性

概要 在计算机系统中&#xff0c;进程管理是一个重要的任务&#xff0c;它涉及创建、启动、监控、终止和管理运行中的进程。Python作为一门强大的编程语言&#xff0c;提供了丰富的库和模块&#xff0c;使得进程管理变得相对容易。本文将介绍如何使用Python来实现系统进程管理…

MQTT基础下载使用

1.下载MQTT(MQTT官网) 下载完后在bin目录下启动cmd 控制台输入emqx start&#xff0c;注意&#xff0c;此时控制台是没有反应的&#xff0c;就回你个D&#xff1a;\EMQX。其实已经打开了。 打开桌面上的MQTTX 并新建连接 这是测试的数据 我订阅了一个test1的订阅 并且我发布…

chrome面向服务的架构SOA

chrome 浏览器面向服务的架构 原来的各种模块会被重构成独立的服务&#xff0c;每个服务都可以独在独立的进程中运行&#xff0c;可以在浏览器的任务管理器中看到各种服务。 "面向服务的架构"&#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09;…

解决mock单元测试中 无法获取实体类xxx对应的表名

错误描述&#xff1a;在执行单元测试时&#xff0c;执行到new Example时抛出异常&#xff0c;提示无法获取实体类xxx对应的表名 Example example new Example(ServeSubscribeRecord.class);Example.Criteria criteria example.createCriteria();criteria.andEqualTo("se…

一步到位:掌握Python中Lambda表达式的5种实用技巧

一步到位&#xff1a;掌握Python中Lambda表达式的5种实用技巧 引言技巧一&#xff1a;单行函数定义技巧二&#xff1a;与内置函数结合技巧三&#xff1a;在数据结构排序中的应用技巧四&#xff1a;作为回调函数技巧五&#xff1a;与函数式编程结合结语 引言 在Python编程的宇宙…

【unity小技巧】Unity音乐和音效管理器

最终效果 前言 在游戏开发中&#xff0c;音乐和音效的管理是一个重要的环节。好的音乐和合适的音效可以为游戏增添氛围并提升玩家的体验。为了更好地管理音乐和音效&#xff0c;我们可以使用一个专门的音乐和音效管理器。 在本文中&#xff0c;我将向大家介绍如何在Unity中创…

气缸功能块(SMART PLC梯形图代码)

有关气缸功能块的更多介绍,可以参考下面链接文章: https://rxxw-control.blog.csdn.net/article/details/125459568https://rxxw-control.blog.csdn.net/article/details/125459568CODESYS平台双通气缸功能块 https://rxxw-control.blog.csdn.net/article/details/12544822…

听GPT 讲Rust源代码--compiler(6)

File: rust/compiler/rustc_index/src/idx.rs 在Rust的源代码中&#xff0c;idx.rs文件位于rust/compiler/rustc_index/src/目录下&#xff0c;它定义了用于索引访问的Idx trait。以下是该文件的详细介绍&#xff1a; Idx是一个基本的整数索引类型&#xff0c;它用于支持Rust编…

C#/.NET/.NET Core优秀项目和框架2023年12月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;公众号每周至少推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文有项目和框架的介绍、功能特点以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学可以优先…

智能分析网关V4智慧港口码头可视化视频智能监管方案

一、需求背景 近年来&#xff0c;水利港口码头正在进行智能化建设&#xff0c;现场管理已经是重中之重。港口作为货物、集装箱堆放及中转机构&#xff0c;具有昼夜不歇、天气多变、环境恶劣等特性&#xff0c;安全保卫工作显得更加重要。港口码头的巡检现场如何高效、快捷地对…

【MySQL·8.0·源码】MySQL 的查询处理

Query processing MySQL 的 Query 处理可以分为 Parse、Prepare(Resolve/Transform)、Optimize 和 Execute 几个阶段 Parse 词法扫描器将 SQL 语句字符串分解为 tokens&#xff0c;语法分析器将 tokens 组装成语法树的子树结构&#xff0c;并 Reduce 为基本查询结构&#xff0…

Centos 磁盘挂载和磁盘扩容(新加硬盘方式)

步骤总结如下 一、对磁盘进行分区 二、对磁盘进行格式化 三、将磁盘挂载到对应目录 四、做开机自动挂载磁盘 磁盘分区 1.使用命令&#xff1a;fdisk -l 查看磁盘&#xff08;注&#xff1a;正常在Centos7中第一块数据盘标识一般是/dev/sda,第二块数据盘标识一般是/dev/sdb&…

小程序一次性订阅消息(消息通知):java服务端实现

文章目录 引言一、消息订阅1.1 小程序订阅消息功能介绍1.2 消息分类1.2.1 新版一次性订阅消息Beta1.2.2 一次性订阅消息&#xff08;用户通过弹窗订阅&#xff09;1.2.3 长期订阅消息&#xff08;用户通过弹窗订阅&#xff09;1.2.4 设备订阅消息 二、获取模板ID1.登录[微信公众…

10款值得推荐的Blazor UI组件库

前言 经常看到有小伙伴在DotNetGuide技术社区交流群里问有什么好用的Blazor UI组件库推荐的&#xff0c;本文将分享一些开源、实用、美观的Blazor UI组件库&#xff0c;提供给广大C#/.NET开发者们学习和使用&#xff08;注意&#xff1a;排名不分先后&#xff0c;都是十分优秀…

算法与数据结构之数组(Java)

目录 1、数组的定义 2、线性结构与非线性结构 3、数组的表现形式 3.1 一维数组 3.2 多维数组 4、重要特性&#xff1a;随机访问 5、ArrayList和数组 6、堆内存和栈内存 7、数组的增删查改 7.1 插入数据 7.2 删除一个数据 7.3 修改数组 7.4 查找数据 8、总结 什么…

CIFAR图片分类数据集

1. CIFAR介绍 官网链接&#xff1a;CIFAR-10 and CIFAR-100 datasets CIFAR-10是一个更接近普适物体的彩色图像数据集。CIFAR-10 是由Hinton 的学生Alex Krizhevsky 和Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含10 个类别的RGB 彩色图片&#xff1a;飞机…

机器学习期末复习

机器学习 选择题名词解释&#xff1a;简答题计算题一、线性回归二、决策树三、贝叶斯 选择题 机器学习利用经验 &#xff0c;须对以下&#xff08;&#xff09;进行分析 A 天气 B 数据 C 生活 D 语言 归纳偏好值指机器学习算法在学习的过程中&#xff0c;对以下&#xff08;&a…

【Java基础篇】 try中return A,catch中return Bfinally中return C,最终返回值是什么?

try中return A&#xff0c;catch中return Bfinally中return C&#xff0c;最终返回值是什么? ✔️典型解析✔️拓展知识仓✔️finally 和 return 的关系 ✔️ final、finally、finalize有什么区别✔️final✔️finally✔️ finalize ✔️典型解析 最终的返回值将会是C 因为 fi…