Python 使用递归实现 DFS 算法,包含示例和详细步骤说明
这张照片由 Shubham Dhage 在 Unsplash 提供
介绍一下在计算机科学中,算法是各种有用技术(如人工智能)的基石,帮助我们高效地解决各种现实生活中的问题。在这些算法中,图算法占据着特殊地位,因为许多问题可以使用图来建模。图是由节点(或顶点)通过边连接而成的集合,表示节点之间的关系(或连接)。
一些例子,比如说:
- 社交网络: 在社交网络中,如 Facebook 或 Instagram,用户可以被表示为节点,而他们之间的友谊或连接可以表示为边。[1]
- 路线规划和导航: 在地图中,位置(城市、交叉路口或地标)被视为节点,而连接这些位置的道路或路径则被视为边。[2]
- 网页抓取: 网络可以被看作是一个巨大的图,其中网页是节点,而它们之间的超链接是边。
- 调度和任务管理: 许多任务依赖关系可以被建模为有向无环图 (DAG),其中任务是节点,而它们之间的依赖关系是边。
- 网络连通性: 在计算机网络中,设备(如路由器和计算机)是节点,而它们之间的通信链路则作为边。
深度优先搜索(DFS)是一种基本的图遍历算法。它用来访问图中所有节点。另一个基本且互补的算法是广度优先搜索(BFS),我们将在另一篇文章中介绍它。
下面,我们将深入了解DFS的工作原理,通过简单的代码示例、直观的例子和酷炫的动画演示,一步步地展示这个算法是如何工作的。
DFS有两种实现方式:迭代和递归。我将在这里教你如何递归地实现它,因为在看来,这种方式更易理解和实现。这也是一个很好的机会,如果你还不熟悉递归,可以学习递归的工作原理。这里将使用纯Python来实现DFS。
以下用于DFS算法的代码。
函数有三个输入:已访问节点的集合(通常为空)、图定义和一个起始节点。逻辑简单,却非常有效:
1. 首先,我们要检查我们是否已经访问过该节点。
如果是,就跳过检查邻居。
b. 否,打印节点并开始访问其邻接节点(即 for 循环)
2. 重复上述步骤,直到所有节点都已在访问过的节点列表中为止。
在这种情况下,该函数返回 None(实际上相当于返回空值),因为它会打印访问过的节点并将这些节点添加到外部定义的集合中。我们可以改变它的行为,使其返回访问过的节点集合而不打印节点。
例1
首先,我们必须将我们的示例图定义为。为此,我们将使用相邻节点的字典作为Python字典形式。在每个键值对中,键是节点,值是与之相连的其他节点列表(相连的节点)。
下面的代码是在计算机内存中创建的第一个示例图,它是一个有向图(为了清晰和简单起见),但深度优先遍历(DFS)同样适用于无向图的情况。
执行一个函数调用命令后,输出是一系列访问过的节点。
图片由作者拍摄。
或者使用如下的代码替代版本。在这里,我们只需对输入做小的改动,不使用全局变量,而是直接传递空集合。输出则为,
图片由作者拍摄
让我们来逐步可视化函数调用栈和最终结果集是如何逐步构建的。下面的动画将逐步展示这个过程。
图片由作者供图
例子 2
在这个例子中,我们将构建并遍历决策树。图结构的定义如下。
对该图执行DFS后,输出结果为:
作者供图
下面的动画显示了图的样子,以及DFS是如何遍历该图的。
DFS算法遍历树;图片来源:作者
总结
深度优先搜索(DFS)是图论中一个基本的算法,在从社交网络到决策树等各个领域中广泛应用。其递归特性使它易于理解和实现,如本文中的示例所示。DFS的简单性及其高效遍历图中所有节点的能力,使其成为解决各种计算问题的有力工具。理解DFS的工作原理有助于掌握其他算法,如广度优先搜索(BFS)和路径查找算法(如Dijkstra 或 A*)。
尝试使用更大和更复杂的图进行实验,并探索这些图在不同数据结构下的行为。“这些图”一词更明确指代“图”。接下来,我们将探讨其他遍历方法,如BFS,并进一步研究它们的应用场景、优点和缺点。
继续练习并突破极限,很快像DFS这样的图算法就会变得轻而易举。加油!编程快乐!
参考资料
[1] Tsok, Samuel & Yakubu, Hosea & Solomon, Rwat. (2023). 关于将图模型应用于Facebook和Facebook Messenger群组的社交媒体网络的研究。国际计算机科学与工程学报。第9卷,第1页。10.56201/ijcsmt.v9.no1.2023.pg1.12. 链接
[2] 代天伦, 郑文超, 孙佳悦, 季村, 周涛, 李明通, 胡威, 余自强, 实时动态图上的连续路由规划,《Procedia计算机科学》期刊, 卷174年(2020) [链接]
共同学习,写下你的评论
评论加载中...
作者其他优质文章