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
0
投稿
猜你喜欢
- WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Interne
- 为什么要写这篇文章经过了若干年的发展,Java逐步从java8升级为java11,java17。让我们对比学习一下最新一版的LTS版本和ja
- 前言本文主要给大家介绍的是关于Java对xls文件进行读写操作的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍:wi
- 1、定义一个接口 Animalpackage com.zh.vo;public interface Animal { void
- 1.实例1(主要看到[2])1.1.系统功能: 开发一个计算器服务CalculateService,这个服务包含加(plus)、减(minu
- InputStreamReader 类1、概述转换流 java.io.InputStreamReader ,是Reader的子类,是从字节流
- 一:SparkSQL1.SparkSQL简介Spark SQL是Spark的一个模块,用于处理结构化的数据,它提供了一个数据抽象DataFr
- Flyway是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式。第一步:pom.xml添加maven依赖<!-- https
- Step1: 安装JDK并配置环境变量;Step2: 安装Gradle进入点击打开链接官网首页点击install gra
- Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。使用Reflections可以很轻松的获取以下
- 本文实例为大家分享了Android登录注册功能的具体代码,供大家参考,具体内容如下展示效果代码区MainActivity(登录方法)publ
- 一、指标监控引入jar包: <dependency> &nb
- MyBatis-Spring允许你在Service Bean中注入映射器。当使用映射器时,就像调用DAO那样来调用映射器就可以了,但是此时你
- Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象。 序列化是
- 前言Spring Boot项目一般都是内嵌tomcat或者jetty服务器运行,很少用war包部署到外部的服务容器,即使放到linux中,一
- 前言在原生的 Android 或 iOS 中,都提供了基本的键值对存储方式,Android 是 SharedPreferences,iOS
- 本文实例为大家分享了Java实现统计字符串出现次数的具体代码,供大家参考,具体内容如下需求:健盘录入一个字符串,要求统计字符串中每个字符串出
- Java语言是SUN(Stanford University Network,斯坦福大学网络公司)公司1995年推出的一门高级编程语言,起初
- 本文实例讲述了Android中TextView显示插入的图片实现方法。分享给大家供大家参考,具体如下:Android系统默认给TextVie
- 1. 在原有工程目录右键-> new ->Module->:2. 选择library:3. 一路next,最后finish