深度优先搜索(DFS)两点之间的可行路径
时间:2022-07-28
本文章向大家介绍深度优先搜索(DFS)两点之间的可行路径,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
DFS是面试中常见的算法,在求路径问题中非常好用。
下面以一个图为例:
假如我们的目标是求点1到点6的所有路径,可以采用深度优先搜索法: 先将节点1加入路径,然后从1的后置节点中选择一个节点,1有两个后置节点,分别是2和3; 这里先选择2,路径为[1,2]; 然后再从2的后置节点中选择,只能选择4,路径为[1,2,4]; 从4的后置节点中选择5,路径为[1,2,4,5]; 从5的后置节点中选择6,路径为[1,2,4,5,6]形成一条完整的从1到6的路径。
这个问题可以由“求从1到6的所有路径”拆解成“从2到6的所有路径”和“从3到6的所有路径”两个问题,然后再往下依次拆解,这种形式的问题可以很方便地采用递归算法解决。
为了演示DFS算法的递归实现,要先将这个图转化为压缩邻接矩阵的形式
graph = [
[2,3],
[4],
[4,6],
[5],
[6],
]
然后进行DFS搜索
paths = []
path = []
def dfs(start,index,end,graph):
path.append(index)
if index == end:
paths.append(path.copy())
path.pop()
else:
for item in graph[index-1]:
if item not in path:
dfs(start,item,end,graph)
path.pop()
dfs(1,1,6,graph)
for i,p in enumerate(paths):
print("path %d" % i + str(p))
output:
path 0[1, 2, 4, 5, 6]
path 1[1, 3, 4, 5, 6]
path 2[1, 3, 6]
递归过程比较难理解,可以在代码中加入print语句,就可以很直观地查看到搜索过程了:
paths = []
path = []
def dfs(start,index,end,graph):
path.append(index)
if index == end:
paths.append(path.copy())
path.pop()
print("找到终点%d,得到路径,往前回溯一位,查看节点%d是否有其他路径" % (index,path[-1]))
else:
print("依次搜索节点%d,%d的后置节点有 %s"% (index,index,str(graph[index-1])))
for item in graph[index-1]:
print("搜索节点%d的后置节点%d" % (index,item))
if item not in path:
dfs(start,item,end,graph)
path.pop()
if path != []:
print("节点%d的后置节点搜索完毕,往前回溯一位,查看节点%d处是否有其他路径" % (index,path[-1]))
else:
print("循环结束,已无其他路径!")
dfs(1,1,6,graph)
for i,p in enumerate(paths):
print("path %d" % i + str(p))
[output]:
依次搜索节点1,1的后置节点有 [2, 3]
搜索节点1的后置节点2
依次搜索节点2,2的后置节点有 [4]
搜索节点2的后置节点4
依次搜索节点4,4的后置节点有 [5]
搜索节点4的后置节点5
依次搜索节点5,5的后置节点有 [6]
搜索节点5的后置节点6
找到终点6,得到路径,往前回溯一位,查看节点5是否有其他路径
节点5的后置节点搜索完毕,往前回溯一位,查看节点4处是否有其他路径
节点4的后置节点搜索完毕,往前回溯一位,查看节点2处是否有其他路径
节点2的后置节点搜索完毕,往前回溯一位,查看节点1处是否有其他路径
搜索节点1的后置节点3
依次搜索节点3,3的后置节点有 [4, 6]
搜索节点3的后置节点4
依次搜索节点4,4的后置节点有 [5]
搜索节点4的后置节点5
依次搜索节点5,5的后置节点有 [6]
搜索节点5的后置节点6
找到终点6,得到路径,往前回溯一位,查看节点5是否有其他路径
节点5的后置节点搜索完毕,往前回溯一位,查看节点4处是否有其他路径
节点4的后置节点搜索完毕,往前回溯一位,查看节点3处是否有其他路径
搜索节点3的后置节点6
找到终点6,得到路径,往前回溯一位,查看节点3是否有其他路径
节点3的后置节点搜索完毕,往前回溯一位,查看节点1处是否有其他路径
循环结束,已无其他路径!
path 0[1, 2, 4, 5, 6]
path 1[1, 3, 4, 5, 6]
path 2[1, 3, 6]
如此一来,是不是一目了然?
- hihoCoder #1043 : 完全背包(板子题)
- 【深度干货】专知主题链路知识推荐#7-机器学习中似懂非懂的马尔科夫链蒙特卡洛采样(MCMC)入门教程02
- hihoCoder #1038 : 01背包(板子题)
- 最小二乘法多项式曲线拟合原理与实现
- HDU 1166 敌兵布阵(线段树单点更新,板子题)
- 一文看懂ovirt的supervdsmd服务
- openstack如何扩展API之二:扩展原有核心API
- selenium+python自动化77-autoit文件上传
- selenium+python自动化78-autoit参数化与批量上传
- libvirt-内存分配和内存热插拔
- selenium+python自动化79-文件下载(SendKeys)
- selenium+python自动化80-文件下载(不弹询问框)
- libvirt-cpu分配和cpu热插拔
- 如何使用curl调试openstack的api
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 图书管理系统(四)图书管理系统实战(2)
- 源码分析之 FactoryBean接口不为人知的秘密
- 图书管理系统(三)图书管理系统实战(1)
- 图书管理系统(二)整合 SSM,你学会了么
- CellChat:细胞间相互作用分析利器
- 我对一类常考算法面试题的详细分析
- Python 面向对象编程(上篇)
- 基于TencentOS-tiny实现PM2.5传感器(攀藤PMSA003)数据解析思路及实现
- Centos7搭建SVN+Apache+iF.SVNAdmin实现web管理SVN
- 安卓最后一个大题复习
- 关于 Spring Ioc,看这一篇就够了!
- 第1次Spring源码学习之@Bean、@Configuration、xml、分析
- Spring 中的依赖注入(DI),你都知道多少?
- Docker配置1台Nginx+3台Tomcat做负载均衡
- Centos7.x+Docker部署RabbitMQ