Java数据结构之图的路径查找算法详解
作者:JAVA旭阳 发布时间:2023-03-27 03:47:11
标签:Java,图,路径,查找
前言
在实际生活中,地图是我们经常使用的一种工具,通常我们会用它进行导航,输入一个出发城市,输入一个目的地
城市,就可以把路线规划好,而在规划好的这个路线上,会路过很多中间的城市。这类问题翻译成专业问题就是:
从s顶点到v顶点是否存在一条路径?如果存在,请找出这条路径。
例如在上图上查找顶点0到顶点4的路径用红色标识出来,那么我们可以把该路径表示为 0-2-3-4。
如果对图的前置知识不了解,请查看系列文章:
【数据结构与算法】图的基础概念和数据模型
【数据结构与算法】图的两种搜索算法
算法详解
我们实现路径查找,最基本的操作还是得遍历并搜索图,所以,我们的实现暂且基于深度优先搜索来完成。其搜索
的过程是比较简单的。我们添加了edgeTo[]
整型数组,这个整型数组会记录从每个顶点回到起点s的路径。
如果我们把顶点设定为0,那么它的搜索可以表示为下图:
总结来说,就是edgeTo
数组的下标表示当前顶点,内容存放上一个节点的数据,根据最终edgeTo的结果,我们很容易能够找到从起点0到任意顶点的路径。
实现
API设计
类名 | DepthFirstPaths |
---|---|
成员变量 | 1.private boolean[] marked: 索引代表顶点,值表示当前顶点是否已经被搜索2.private int s:起点3.private int[] edgeTo:索引代表顶点,值代表从起点s到当前顶点路径上的最后一个顶点 |
构造方法 | DepthFirstPaths(Graph G,int s):构造深度优先搜索对象,使用深度优先搜索找出G图中起点为s的所有路径 |
成员方法 | 1.private void dfs(Graph G, int v):使用深度优先搜索找出G图中v顶点的所有相邻顶点2.public boolean hasPathTo(int v):判断v顶点与s顶点是否存在路径3.public Stack pathTo(int v):找出从起点s到顶点v的路径(就是该路径经过的顶点) |
代码实现
/**
* 路径查找
*
* @author alvin
* @date 2022/10/31
* @since 1.0
**/
public class DepthFirstPaths {
//索引代表顶点,值表示当前顶点是否已经被搜索
private boolean[] marked;
//起点
private int s;
//索引代表顶点,值代表从起点s到当前顶点路径上的最后一个顶点
private int[] edgeTo;
//构造深度优先搜索对象,使用深度优先搜索找出G图中起点为s的所有路径
public DepthFirstPaths(Graph G, int s){
//初始化marked数组
this.marked = new boolean[G.V()];
//初始化起点
this.s = s;
//初始化edgeTo数组
this.edgeTo = new int[G.V()];
dfs(G,s);
}
//使用深度优先搜索找出G图中v顶点的所有相邻顶点
private void dfs(Graph G, int v){
//把v表示为已搜索
marked[v] = true;
//遍历顶点v的邻接表,拿到每一个相邻的顶点,继续递归搜索
for (Integer w : G.adj(v)) {
//如果顶点w没有被搜索,则继续递归搜索
if (!marked[w]){
edgeTo[w] = v;//到达顶点w的路径上的最后一个顶点是v
dfs(G,w);
}
}
}
//判断w顶点与s顶点是否存在路径
public boolean hasPathTo(int v){
return marked[v];
}
//找出从起点s到顶点v的路径(就是该路径经过的顶点)
public Stack<Integer> pathTo(int v){
if (!hasPathTo(v)){
return null;
}
//创建栈对象,保存路径中的所有顶点
Stack<Integer> path = new Stack<>();
//通过循环,从顶点v开始,一直往前找,到找到起点为止
for (int x = v; x!=s;x = edgeTo[x]){
path.push(x);
}
//把起点s放到栈中
path.push(s);
return path;
}
}
测试:
public class DepthFirstPathsTest {
@Test
public void test() {
//城市数量
int totalNumber = 20;
Graph G = new Graph(totalNumber);
//添加城市的交通路线
G.addEdge(0,1);
G.addEdge(6,9);
G.addEdge(1,8);
G.addEdge(1,12);
G.addEdge(8,12);
G.addEdge(6,10);
G.addEdge(4,8);
DepthFirstPaths depthFirstPaths = new DepthFirstPaths(G, 0);
Stack<Integer> path = depthFirstPaths.pathTo(12);
StringBuilder sb = new StringBuilder();
//遍历栈对象
for (Integer v : path) {
sb.append(v+"->");
}
sb.deleteCharAt(sb.length()-1);
sb.deleteCharAt(sb.length()-1);
System.out.println(sb);
}
}
来源:https://juejin.cn/post/7160669091970154510


猜你喜欢
- 1:在 Visual Studio Code 中打开扩展视图(Ctrl+Shift+X),输入关键词java、spring分别下载Java开
- 自定义Starter命名规则注意artifactId的命名规则,Spring官方Starter通常命名为spring-boot-starte
- 本文实例讲述了Android编程实现画板功能的方法。分享给大家供大家参考,具体如下:Android实现画板主要有2种方式,一种是用自定义Vi
- Application对象Application对象生存期和Web应用程序生存期一样长,生存期从Web应用程序网页被访问开始,HttpApp
- 常用命令:打包:mvn package编译:mvn compile清空:mvn clean(清除编译后目录,默认是target目录)运行测试
- 一、JAVA简要概述先说一下java之父,詹姆斯·高斯林这是一个爱喝咖啡而又强大的男人。再来看一下JAVA有多火在TIOBE排行榜上JAVA
- 前面有写到Spring+SpringMVC+MyBatis深入学习及搭建(二)——MyBatis原始Dao开发和mapper代理开发MyBa
- 对于某些程序,我们只允许它使用某些特定端口、网络类型或者特定IP类型等信息。这时候,需要使用到防火墙里面的“高级设置”,创建某些特定的入站或
- 背景近期因实际项目需要,在特定操作下触发定位请求,取到用户位置及附近位置。问题:经初步选型,最终决定接入百度定位,按照百度定位SDK And
- 本文实例为大家分享了android studio实现简单计算器的具体代码,供大家参考,具体内容如下布局:<?xml version=&
- 在本系列文章中,我们将使用深度神经网络(DNN)来执行硬币识别。具体来说,我们将训练一个DNN识别图像中的硬币。在本文中,我们将描述一个Op
- 前言想在锁屏上面实现弹窗,第一个想法就是利用 WindowManager 设置 Window 的 Flag,通过设置 Flag 的显示优先级
- 创建两个场景同时赋值StaticVarious 脚本 然后按键好,H ,J 进行不断切换场景,会发现unity 控制台输出数字不断增加,然后
- 今天在别人的代码基础上实现新需求,看到对于mybatis查询结果的判断不是很正确,如果查询结果为空就会异常,不知道大家有没有这样的疑惑:my
- Android RadioButton 图片位置与大小Java:rgGroup = (RadioGroup) findViewById(R.
- Java 获取文件大小今天写代码时需要实现获取文件大小的功能,目前有两种实现方法,一种是使用File的length()方法;另外
- 本周的谷歌I/O大会带来了很多关于Android的振奋人心的消息。可能我们需要较长的时间来消化Android L引入的新东西。这些天我一直在
- 前言相信有很多小伙伴,在日常的开发中都有遇到过需要调用第三方接口的需求吧,但是自己有没有写过接口提供给第三方使用呢,常规的都是我们调用别人的
- Bottom SheetBottom Sheet 是 Design Support Library 23.2 版本引入的一个类似于对话框的控
- java通过IP解析地理位置在项目开发中,需要在登录日志或者操作日志中记录客户端ip所在的地理位置。目前根据ip定位地理位置的第三方api有