PYTHON实现图的深度优先搜索(DFS)和广度优先搜索(BFS)算法

使用邻接表来表示图的结构,Python 代码演示邻接表的深度优先遍历和广度优先遍历的实现。


# 深度优先搜索(Depth-First Search, DFS)算法函数
# 使用集合来记录已经访问过的节点,在遍历过程中递归访问每个节点的邻居节点,并打印访问顺序。
def dfs(graph, start, visited=None):# 若visited参数未提供,则初始化为Noneif visited is None:# 使用集合存储已访问的节点,确保每个节点只被访问一次visited = set()# 将当前起始节点添加到已访问节点集合中visited.add(start)# 打印当前节点,表示访问了该节点print(start)# 遍历当前节点的邻居节点for neighbor in graph[start] - visited:# 对未访问过的邻居节点进行递归调用DFS函数dfs(graph, neighbor, visited)# 返回最终访问过的所有节点集合return visited# 定义图的邻接表结构
graph = {'A': {'B', 'C'},'B': {'A', 'D', 'E'},'C': {'A', 'F'},'D': {'B'},'E': {'B', 'F'},'F': {'C', 'E'}
}# 从'A'节点开始执行深度优先搜索
dfs(graph, 'A')print('----------------------------------')# 广度优先搜索(Breadth-First Search, BFS)算法函数
# 利用双端队列和集合数据结构实现了广度优先搜索的原理,按照逐层扩展探索的方式遍历整个图并输出访问顺序。
from collections import dequedef bfs(graph, start):# 使用集合存储已访问的节点,确保每个节点只被访问一次visited = set()# 使用双端队列(deque)来实现BFS的队列结构,从起始点开始探索queue = deque([start])# 将起始节点标记为已访问visited.add(start)# 当队列不为空时循环执行BFSwhile queue:# 从队列左侧取出顶点作为当前节点vertex = queue.popleft()# 打印当前节点,表示访问了该节点print(vertex)# 遍历当前节点的邻居节点for neighbor in graph[vertex] - visited:# 将未访问过的邻居节点加入已访问集合和队列中visited.add(neighbor)queue.append(neighbor)# 定义图的邻接表结构
graph = {'A': {'B', 'C'},'B': {'A', 'D', 'E'},'C': {'A', 'F'},'D': {'B'},'E': {'B', 'F'},'F': {'C', 'E'}
}# 从'A'节点开始执行广度优先搜索
bfs(graph, 'A')

简要解释一下这两种遍历算法的原理和代码实现。

深度优先遍历算法原理:

深度优先遍历 (Depth First Search, DFS) 是一种用于遍历或搜索树或图的算法。在这种遍历过程中,从起始顶点开始,沿着路径一直走到最深处,直到不能再前进为止,然后返回上一级,继续探索未被访问的分支。这一过程是递归的。深度优先遍历在图中一般使用栈来实现。

深度优先遍历算法实现:

  1. 创建一个布尔数组 visited[],用于记录顶点是否已被访问过。
  2. 从给定的起始顶点开始,递归地遍历该顶点的所有未访问过的邻接顶点。
  3. 在访问每个顶点时,将其标记为已访问,并递归地遍历其邻接顶点。
  4. 重复以上步骤,直到所有可达的顶点都被访问过。

广度优先遍历算法原理:

广度优先遍历 (Breadth First Search, BFS) 也是一种用于遍历或搜索树或图的算法。在这种遍历过程中,从起始顶点开始,依次访问该顶点的所有邻接顶点,然后再依次访问这些邻接顶点的邻接顶点,以此类推,直到图中所有可达顶点都被访问。广度优先遍历一般使用队列来实现。

广度优先遍历算法实现:

  1. 创建一个布尔数组 visited[],用于记录顶点是否已被访问过。
  2. 创建一个空队列 queue,用于存储待访问的顶点。
  3. 将起始顶点加入队列,并标记为已访问。
  4. 从队列中取出一个顶点,访问其所有未被访问过的邻接顶点,并将这些邻接顶点加入队列中。
  5. 重复以上步骤,直到队列为空。

这两种遍历算法都具有其独特的应用场景和优劣势,选择哪种算法取决于具体问题的要求和性质。

-------------------

这段代码定义了一个图(Graph)类,实现了图的深度优先搜索(DFS)和广度优先搜索(BFS)算法。使用邻接表来表示图的结构。下面是对代码中各个部分的详细注释:

  • __init__(self): 类的初始化方法,初始化一个空的邻接表图。

  • add_edge(self, u, v): 添加边的方法,将顶点u和v之间的边加入图中。

  • dfs_util(self, v, visited): 深度优先搜索的辅助方法,以顶点v为起点进行深度优先搜索,并标记已访问过的顶点。

  • dfs(self, v): 深度优先搜索方法,以顶点v为起点进行深度优先搜索。

  • bfs(self, v): 广度优先搜索方法,以顶点v为起点进行广度优先搜索。

在下面的代码部分,首先创建了两个图实例,分别进行了深度优先搜索和广度优先搜索,并输出了搜索结果。

from collections import defaultdictclass Graph:def __init__(self):# 使用 defaultdict(list) 创建了一个默认值为列表的字典,用于存储图的邻接表self.graph = defaultdict(list)def add_edge(self, u, v):"""添加边的方法:param u: 边的起始顶点:param v: 边的终止顶点"""self.graph[u].append(v)  # 将终止顶点添加到起始顶点的邻接列表中def dfs_util(self, v, visited):"""深度优先搜索的辅助函数:param v: 当前顶点:param visited: 用于标记顶点是否已被访问的列表"""visited[v] = True  # 将当前顶点标记为已访问print(v, end=' ')  # 打印当前顶点for i in self.graph[v]:if not visited[i]:self.dfs_util(i, visited)  # 递归调用深度优先搜索函数访问当前顶点的未访问邻接顶点def dfs(self, v):"""深度优先搜索方法:param v: 搜索起始顶点"""visited = [False] * (max(self.graph) + 1)  # 创建标记列表,初始时所有顶点均未被访问self.dfs_util(v, visited)  # 调用深度优先搜索辅助函数def bfs(self, v):"""广度优先搜索方法:param v: 搜索起始顶点"""visited = [False] * (max(self.graph) + 1)  # 创建标记列表,初始时所有顶点均未被访问queue = []  # 创建空队列,用于存储待访问顶点queue.append(v)  # 将起始顶点加入队列visited[v] = True  # 将起始顶点标记为已访问while queue:v = queue.pop(0)  # 取出队列中的第一个顶点print(v, end=' ')  # 打印当前访问的顶点for i in self.graph[v]:if not visited[i]:queue.append(i)  # 将未访问过的邻接顶点加入队列visited[i] = True  # 标记邻接顶点为已访问# 邻接表的深度遍历
print("邻接表的深度遍历:")
g_dfs = Graph()
g_dfs.add_edge(0, 1)
g_dfs.add_edge(0, 2)
g_dfs.add_edge(1, 2)
g_dfs.add_edge(2, 0)
g_dfs.add_edge(2, 3)
g_dfs.add_edge(3, 3)g_dfs.dfs(2)  # 从顶点2开始深度优先遍历print("\n")# 邻接表的广度遍历
print("邻接表的广度遍历:")
g_bfs = Graph()
g_bfs.add_edge(0, 1)
g_bfs.add_edge(0, 2)
g_bfs.add_edge(1, 2)
g_bfs.add_edge(2, 0)
g_bfs.add_edge(2, 3)
g_bfs.add_edge(3, 3)g_bfs.bfs(2)  # 从顶点2开始广度优先遍历

解释一下def bfs(self, v):的功能:

  1. bfs(self, v): 这是一个类方法,用于执行广度优先搜索。它接受一个参数 v,表示搜索的起始顶点。

  2. visited = [False] * (max(self.graph) + 1): 创建一个布尔类型的列表 visited,用于标记顶点是否已被访问过。列表的长度为图中顶点编号的最大值加一,初始化所有元素为 False

  3. queue = []: 创建一个空队列,用于存储待访问的顶点。

  4. queue.append(v): 将起始顶点 v 加入队列,并将其标记为已访问。

  5. while queue:: 当队列不为空时,执行循环,表示还有顶点需要被访问。

  6. v = queue.pop(0): 从队列中取出一个顶点 v,并将其从队列中移除。这里使用 pop(0) 表示从队列的头部取出元素,即先进先出。

  7. print(v, end=' '): 打印当前访问的顶点 v

  8. for i in self.graph[v]:: 遍历当前顶点 v 的所有邻接顶点。

  9. if not visited[i]:: 如果邻接顶点 i 还未被访问过,则将其加入队列,并标记为已访问。

这样,通过不断将邻接顶点加入队列,直到队列为空,就完成了广度优先搜索算法的执行过程。在执行过程中,顶点的访问顺序按照它们距离起始顶点的距离逐层增加,因此可以实现广度优先的搜索策略。

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

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

相关文章

树莓派点亮LED灯

简介 使用GPIO Zero library 的 Python库实现点亮LED灯。接线 树莓派引脚参考图如下: LED正极 接GPIO17 LED负极 接GND 权限 将你的用户加到gpio组中, 否则无法控制GPIO sudo usermod -a -G gpio 代码 from gpiozero import LED from time impor…

ES全文检索支持拼音和繁简检索

ES全文检索支持拼音和繁简检索 1. 实现目标2. 引入pinyin插件2.1 编译 elasticsearch-analysis-pinyin 插件2.2 安装拼音插件 3. 引入ik分词器插件3.1 已有作者编译后的包文件3.2 只有源代码的版本3.3 安装ik分词插件 4. 建立es索引5.测试检索6. 繁简转换 1. 实现目标 ES检索时…

Springboot+Vue+小程序+基于微信小程序护农远程看护系统

开发平台为idea,maven管理工具,Mybatis操作数据库,根据市场数字化需要为农户打造小程序可远程查看农场的种植情况。项目是调试,讲解服务均可有偿获取,需要可在最下方QQ二维码处联系我。 SpringbootVue小程序&#xff…

【UE5】数字人基础

这里主要记录一下自己在实现数字人得过程中涉及导XSens惯性动捕,视频动捕,LiveLinkFace表捕,GRoom物理头发等。 一、导入骨骼网格体 骨骼网格体即模型要在模型雕刻阶段就要雕刻好表捕所需的表情体(blendshape),后面表捕的效果直…

API安全

一,什么是API API指的是应用程序编程接口(Application Programming Interface),是一组定义了软件组件如何相互交互的规范。通过API,不同的软件可以相互通信和交换数据,实现不同软件之间的集成和互操作。 …

代码随想录算法训练营DAY45|C++动态规划Part7|70.爬楼梯(进阶版)、322. 零钱兑换、279.完全平方数

文章目录 70.爬楼梯(进阶版)322. 零钱兑换思路CPP代码 279.完全平方数思路CPP代码 70.爬楼梯(进阶版) 卡码网:57. 爬楼梯 文章讲解:70.爬楼梯(进阶版) 322. 零钱兑换 力扣题目链接 文章讲解:322…

llama_index微调BGE模型

微调模型是为了让模型在特殊领域表现良好,帮助其学习到专业术语等。 本文采用llama_index框架微调BGE模型,跑通整个流程,并学习模型微调的方法。 一、环境准备 Linux环境,GPU L20 48G,Python3.8.10。 pip该库即可。 二、数据准备 该框架实现了读取各种类型的文件,给…

LNMP部署及应用(Linux+Nginx+MySQL+PHP)

LNMP 我们为什么采用LNMP这种架构? 采用Linux、PHP、MySQL的优点我们不必多说。 Nginx是一个小巧而高效的Linux下的Web服务器软件,是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,已经在一些俄罗斯的大型网站上运行多年,目…

数据分析及AI技术在旅游行业的应用

引言 旅游行业是一个充满潜力和机遇的领域,而数据分析和人工智能(AI)技术的迅猛发展为这个行业带来了前所未有的机遇和挑战。本文将探讨数据分析及AI技术在旅游行业中的具体应用及其带来的影响。 数据分析在旅游行业的4种应用 在旅游行业…

windows编程中的位图操作,界面中插入位图方法

在界面中插入位图,主要用到BitBlt这个函数 BOOL CDC::BitBlt(int x, int y, int width, int height, CDC *src, int src_x, int src_y, DWORD dwRop)用法说明见官方说明 这里要注意的是,这个函数是把源图像从src这个设备上下文传递到目标设备上下文(这…

LangChain:1. Prompt基本使用

1. Prompt基本使用 from langchain_core.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate这里有两种prompt,其对应两种形式:PromptTemplate 和 ChatPromptTemplate 从某种意义来说,前者是一个通用形…

如何从 iPhone 恢复已删除或丢失的联系人?

不小心删除了您的 iPhone 联系人?不用担心。我们将向您展示如何从 iPhone或 iPad恢复已删除或丢失的联系人。当您从 iPhone 中删除联系人时,您可能认为无法将其恢复。但事实是,您可以从 iPhone 或 iPad 恢复已删除的联系人,因为它…

链表经典练习题

目录 前言: 一、反转单链表 二、链表的中间结点 三、合并两个有序链表 四、分割链表 五、约瑟夫问题 六、判断链表是否有环? 七、求环形链表的入口点 八、输入一个链表,输出该链表中倒数第k个结点 九、输入两个链表,找出…

云原生Kubernetes: K8S 1.29版本 部署Sonarqube

一、实验 1.环境 (1)主机 表1 主机 主机架构版本IP备注masterK8S master节点1.29.0192.168.204.8 node1K8S node节点1.29.0192.168.204.9node2K8S node节点1.29.0192.168.204.10已部署Kuboard (2)master节点查看集群 1&…

开箱子咸鱼之王H5游戏源码_内购修复优化_附带APK完美运营无bug最终版__GM总运营后台_附带安卓版本

内容目录 一、详细介绍二、效果展示2.效果图展示 三、学习资料下载 一、详细介绍 1.包括原生打包APK,资源全部APK本地化,基本上不跑服务器宽带 2.优化后端,基本上不再一直跑内存,不炸服响应快! 3.优化前端&#xff0c…

WSL2-Ubuntu使用Conda配置百度飞浆paddlepaddle虚拟环境

0x00 缘起 本文将介绍在WSL2-Ubuntu系统中,使用Conda配置百度飞浆paddlepaddle虚拟环境中所出现的各种问题以及解决方法,最终运行"run_check()"通过测试。 在WSL2中配置paddlepaddle不像配置Pytorch那样顺滑,会出现各种问题(如:库的文件缺失、不知道如何匹配C…

设计模式-02 设计模式-接口隔离原则案例分析

1.定义 接口隔离原则(Interface Segregation Principle,简称 ISP)是设计模式中的一个原则,它规定客户端不应该依赖它不使用的方法。 换句话说,接口应该被细分为更小的、更具体的接口,以便客户端只依赖于它…

Hive 与 MySQL 的数据库限制对比

数据库的大小 Hive: 由于Hive是建立在Hadoop生态系统之上,理论上其数据库大小仅受Hadoop分布式文件系统(HDFS)的限制,可以达到PB级别或更高。MySQL: MySQL数据库的大小受到磁盘空间和文件系统的限制。在实践中,单个实例…

Web后端开发中对三层架构解耦之控制反转与依赖注入

内聚与耦合 内聚 比如说我们刚刚书写的员工的实现类 在这里我们仅仅书写的是和员工相关的代码 而与员工无关的代码都没有放到这里 说明内聚程度较高 耦合 以后软件开发要高内聚 低耦合 提高程序灵活性 扩拓展性 分析代码 如何解耦 创建容器 提供一个容器 存储东西 存储E…

STM32 F103C8T6学习笔记16:1.3寸OLED的驱动显示日历

今天尝试使用STM32 F103C8T6驱动显示 1.3寸的OLED,显示数字、字符串、汉字、图片等 本质与0.96寸的OLED是完全相同的原理: 而且经过我的研究发现: 1.3寸大小的OLED并未比0.96寸的有更多的显示像素点数来显示,也是128*64的像素点数显示: 也…