当前位置: 首页 > news >正文

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

一、图的遍历的定义:

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

二、深度优先遍历(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

}

相关文章:

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

一、图的遍历的定义&#xff1a; 从图的某个顶点出发访问遍图中所有顶点&#xff0c;且每个顶点仅被访问一次。&#xff08;连通图与非连通图&#xff09; 二、深度优先遍历&#xff08;DFS&#xff09;&#xff1b; 1、访问指定的起始顶点&#xff1b; 2、若当前访问的顶点…...

抖店做不起来?新手常见起店失败问题总结,看下你中了几条?

我是王路飞。 能看到这篇文章的&#xff0c;肯定是处境符合标题内容了。 抖店的门槛很低&#xff0c;运营思路其实也不算难&#xff0c;但就是很多新手做不起来。 这中间&#xff0c;可能跟平台、项目没什么关系&#xff0c;而是跟你自己有关系&#xff0c;走错了方向&#…...

【每日面试题】精选java面试题之redis

Redis是什么&#xff1f;为什么要使用Redis&#xff1f; Redis是一个开源的高性能键值对存储数据库。它提供了多种数据结构&#xff0c;包括字符串、列表、集合、有序集合、哈希表等。Redis具有快速、可扩展、持久化、支持多种数据结构等特点&#xff0c;适用于缓存、消息队列…...

OSCP 靶场 - Vault

端口扫描 nmap nmap -O 192.168.162.172 smb枚举 smbmap(kali自带) //枚举GUEST用户可以使用的目录 smbmap -u GUEST -H 192.168.162.172 NTLMrelay—smbrelay 1.制作钓鱼文件 使用GitHub - xct/hashgrab: generate payloads that force authentication against an attacker…...

uniapp子组件向父组件传值

目录 子组件向父组件传值子组件1子组件2 父组件最后 子组件向父组件传值 子组件1 <template><view class"content"><view v-for"(item,index) in list" :key"index">{{item}}</view></view> </template>&…...

过滤特殊 微信昵称

$nickName preg_replace(/[\xf0-\xf7].{3}/, , $userData[nickName]);...

LLM、AGI、多模态AI 篇一:开源大语言模型简记

文章目录 系列开源大模型LlamaChinese-LLaMA-AlpacaLlama2-ChineseLinlyYaYiChatGLMtransformersGPT-3(未完全开源)BERTT5QwenBELLEMossBaichuan...

微信小程序中获取用户当前位置的解决方案

微信小程序中获取用户当前位置的解决方案 1 概述 微信小程序有时需要获取用户当前位置&#xff0c;以便为用户提供基于位置信息的服务&#xff08;附近美食、出行方案等&#xff09;。 获取用户当前位置的前提是用户手机需要打开 GPS 定位开关&#xff1b;其次&#xff0c;微…...

Vue3-35-路由-路由守卫的简单认识

什么是路由守卫 路由守卫&#xff0c;就是在 路由跳转 的过程中&#xff0c; 可以进行一些拦截&#xff0c;做一些逻辑判断&#xff0c; 控制该路由是否可以正常跳转的函数。常用的路由守卫有三个 &#xff1a; beforeEach() : 前置守卫&#xff0c;在路由 跳转前 就会被拦截&…...

制药企业符合CSV验证需要注意什么?

在制药行业中&#xff0c;计算机化系统验证&#xff08;CSV&#xff09;是确保生产过程的合规性和数据完整性的关键要素。通过CSV验证&#xff0c;制药企业可以保证其计算机化系统的可靠性和合规性&#xff0c;从而确保产品质量和患者安全。然而&#xff0c;符合CSV验证并不是一…...

再谈动态SQL

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…...

【数据结构】树

一.二叉树的基本概念和性质&#xff1a; 1.二叉树的递归定义&#xff1a; 二叉树或为空树&#xff0c;或是由一个根结点加上两棵分别称为左子树和右子树的、互不相交的二叉树组成 2.二叉树的特点&#xff1a; &#xff08;1&#xff09;每个结点最多只有两棵子树&#xff0…...

【Midjourney】AI绘画新手教程(一)登录和创建服务器,生成第一幅画作

一、登录Discord 1、访问Discord官网 使用柯學尚网&#xff08;亲测非必须&#xff0c;可加快响应速度&#xff09;访问Discord官方网址&#xff1a;https://discord.com 选择“在您的浏览器中打开Discord” 然后&#xff0c;注册帐号、购买套餐等&#xff0c;在此不做缀述。…...

对比 PyTorch 和 TensorFlow:选择适合你的深度学习框架

目录 引言 深度学习在各行业中的应用 PyTorch 和 TensorFlow 简介 PyTorch&#xff1a;简介与设计理念 发展历史和背景 主要特点和设计理念 TensorFlow&#xff1a;简介与设计理念 发展历史和背景 主要特点和设计理念 PyTorch 和 TensorFlow 的重要性 Pytorch对比Te…...

Oracle笔记-查看表已使用空间最大空间

目前以Oracle18c为例&#xff0c;主要是查这个表USER_SEGMENTS。 在 Oracle 18c 数据库中&#xff0c;USER_SEGMENTS 是一个系统表&#xff0c;用于存储当前用户&#xff08;当前会话&#xff09;拥有的所有段的信息。段是 Oracle 中分配存储空间的逻辑单位&#xff0c;用于存…...

大数据HCIE成神之路之特征工程——特征选择

特征选择 1.1 特征选择 - Filter方法1.1.1 实验任务1.1.1.1 实验背景1.1.1.2 实验目标1.1.1.3 实验数据解析1.1.1.4 实验思路 1.1.2 实验操作步骤 1.2 特征选择 - Wrapper方法1.2.1 实验任务1.2.1.1 实验背景1.2.1.2 实验目标1.2.1.3 实验数据解析1.2.1.4 实验思路 1.2.2 实验操…...

python 正则-常见题目

1、邮箱 print(re.findall(r[\w-][\w-]\.[\w-], weidianqq.com))2、身份证号 xxxxxx yyyy MM dd 375 0 十八位 print(re.findall(r(?:18|19|(?:[23]\d))\d{2}, 2010)) # 年print(re.findall(r(?:0[1-9])|10|11|12, 11)) # 月print(re.findall(r(?:[0-2][1-9])|10|20|30|3…...

解析:Eureka的工作原理

Eureka是Netflix开源的一个基于REST的的服务发现注册框架&#xff0c;它遵循了REST协议&#xff0c;提供了一套简单的API来完成服务的注册和发现。Eureka能够帮助分布式系统中的服务提供者自动将自身注册到注册中心&#xff0c;同时也能够让服务消费者从注册中心发现服务提供者…...

RecyclerView 与 ListView 区别和使用

前置知识&#xff1a;ListView基本用法与性能提升 RecyclerView 与 ListView 区别 RecyclerView 需要设置布局&#xff08;LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager&#xff09; recyclerView?.layoutManager LinearLayoutManager(activity) …...

力扣232. 用栈实现队列

题目 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并返回元素int peek() 返回队列开…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

Python学习(8) ----- Python的类与对象

Python 中的类&#xff08;Class&#xff09;与对象&#xff08;Object&#xff09;是面向对象编程&#xff08;OOP&#xff09;的核心。我们可以通过“类是模板&#xff0c;对象是实例”来理解它们的关系。 &#x1f9f1; 一句话理解&#xff1a; 类就像“图纸”&#xff0c;对…...

ThreadLocal 源码

ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物&#xff0c;因为每个访问一个线程局部变量的线程&#xff08;通过其 get 或 set 方法&#xff09;都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段&#xff0c;这些类希望将…...