Dijkstra算法——邻接矩阵实现+路径记录

news2024/11/18 1:24:45

本文是在下面这篇文章的基础上做了一些补充,增加了路径记录的功能。具体Dijkstra的实现过程可以参考下面的这篇文章。
[jarvan:Dijkstra算法详解 通俗易懂](Dijkstra算法详解 通俗易懂 - jarvan的文章 - 知乎
https://zhuanlan.zhihu.com/p/338414118)

创建 GraphAdjMat 类
GraphAdjMat 类用来实现图的邻接矩阵,方便后续的测试,具体代码如下:

package algorithm.graph;

import java.util.ArrayList;
import java.util.List;

public class GraphAdjMat {
	
	private List<Integer> vertices;
	private List<List<Integer>> adjMat;
	
	/**
	 * 构造函数
	 * @param vertices 顶点列表
	 * @param edges 边
	 */
	public GraphAdjMat(int[]vertices, int[][]edges) {
		this.vertices = new ArrayList<>();
		this.adjMat = new ArrayList<>();
		for(int v : vertices) {
			addVertex(v);
		}
		for(int[]e : edges) {
			addEdge(e[0],e[1],e[2]);
		}
		//设置顶点自己到自己的权重为0
		for(int i=0; i<vertices.length; i++) {
			this.adjMat.get(i).set(i, 0);
		}
	}
	
	public List<List<Integer>> getAdjMat() {
		return this.adjMat;
	}
	
	/**
	 * 添加顶点
	 */
	public void addVertex(int val) {
		int n = vertices.size();
		vertices.add(val);
		List<Integer> newRow = new ArrayList<>();
		for(int i=0; i<n; i++) {
			newRow.add(-1);
		}
		adjMat.add(newRow);
		for(List<Integer> row : adjMat) {
			row.add(-1);
		}
	}
	
	/**
	 * 移除顶点
	 */
	public void removeVertex(int index) {
		if(index < 0 || index >= vertices.size()) {
			throw new IndexOutOfBoundsException();
		}
		vertices.remove(index);
		adjMat.remove(index);
		for(List<Integer> row : adjMat) {
			row.remove(index);
		}
	}
	
	/**
	 * 添加边
	 * @param i 顶点1
	 * @param j 顶点2
	 * @param weight 边权重
	 */
	public void addEdge(int i, int j, int weight) {
		if(i<0||j<0||i>=vertices.size()||j>=vertices.size()||i==j) {
			throw new IndexOutOfBoundsException();
		}
		adjMat.get(i).set(j, weight);
		adjMat.get(j).set(i, weight);
	}
	
	/**
	 * 移除边
	 */
	public void removeEdge(int i, int j) {
		if(i<0||j<0||i>=vertices.size()||j>=vertices.size()||i==j) {
			throw new IndexOutOfBoundsException();
		}
		adjMat.get(i).set(j, -1);
		adjMat.get(j).set(i, -1);
	}
	
	public void print() {
		System.out.println("adj mat:");
		for(List<Integer> row : adjMat) {
			for(int v : row) {
				System.out.printf("%3d", v);
			}
			System.out.println();
		}
	}

}

GraphAdjMat 类中提供了增加顶点、移除顶点、增加边和移除边的操作。
创建 DijkstraAlg 类
该类用于实现 Dijkstra 算法,并打印指定点到所有点的最短距离和路径信息

package algorithm.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Dijkstra 算法
 */
public class DijkstraAlg {

	public static void main(String[]args) {
		char[]vertexNames = {'A','B','C','D'};
		int[]vertices = {1,2,3,4};
		int[][]edges = {{0,1,1},{0,3,6},{1,2,4},{1,3,1},{2,3,1}};
		//构建邻接矩阵
		GraphAdjMat adjMat = new GraphAdjMat(vertices, edges);
		adjMat.print();
		int startVertex = 0;
		List<ShortestPath> result = dijkstra(adjMat.getAdjMat(),startVertex);
		System.out.println("dijkstra result: ");
		for(int i=0; i<vertexNames.length; i++) {
			System.out.printf("%3s -> %s distence : %d ; ",vertexNames[startVertex], vertexNames[i], result.get(i).distence);
			List<Integer> path = result.get(i).path;
			System.out.print("A -> ");
			for(int j=0; j<path.size(); j++) {
				if(j < path.size()-1) {					
					System.out.printf("%s -> ",vertexNames[path.get(j)]);
				}else {
					System.out.printf("%s\n", vertexNames[path.get(j)]);
				}
			}
		}
	}
	
	public static List<ShortestPath> dijkstra(List<List<Integer>> graph, int startVertex) {
		int len = graph.size();
		List<ShortestPath> result = new ArrayList<>(len);
		int[]notFound = new int[len];
		//初始化 result
		for(int i=0; i<len; i++) {
			ShortestPath shortestPath = new ShortestPath();
			shortestPath.distence = -1;
			shortestPath.path = new ArrayList<>();
			result.add(i, shortestPath);
		}
		ShortestPath startVertexPath = new ShortestPath();
		startVertexPath.distence = 0;
		startVertexPath.path = new ArrayList<>(0);
		result.set(startVertex,startVertexPath);
		//初始化 notFound
		for(int i=0; i<len; i++) {
			notFound[i] = graph.get(startVertex).get(i);
		}
		notFound[startVertex] = -1;
		//开始 Dijkstra 算法
		Map<Integer,List<Integer>> recordPathMap = new HashMap<>();
		for(int i=1; i<len; i++) {
			int min = Integer.MAX_VALUE;
			int minIndex = 0;
			for(int j=0; j<len; j++) {
				if(notFound[j] > 0 && notFound[j] < min) {
					min = notFound[j];
					minIndex = j;
				}
			}
			result.get(minIndex).distence = min;
			notFound[minIndex] = -1;
			//刷新 notFound
			for(int j=0; j<len; j++) {
				//graph.get(minIndex).get(j) > 0 用来确保 minIndex 顶点有边,result[j] == -1 用来确保 j 点没有在结果集中
				if(graph.get(minIndex).get(j) > 0 && result.get(j).distence == -1) {
					int newDistence = result.get(minIndex).distence + graph.get(minIndex).get(j);
					//计算合并距离如果小于直接到j点的距离,或者无法到达j点事将新距离刷新到notFound中
					if(newDistence < notFound[j] || notFound[j] == -1) {
						notFound[j] = newDistence;
						if(!recordPathMap.containsKey(j)) {
							List<Integer> tempList = new ArrayList<>(1);
							tempList.add(minIndex);
							recordPathMap.put(j, tempList);
						}else {							
							recordPathMap.get(j).add(minIndex);
						}
					}
				}
			}
		}
		System.out.println(recordPathMap);
		//推到路径
		for(int i=0; i<len; i++) {
			result.get(i).path.addAll(recordPathMap.getOrDefault(i, new ArrayList<>()));
			result.get(i).path.add(i);
		}
		return result;
	}
	
	public static void printArr(int[]arr, String arrName) {
		System.out.print(arrName);
		for(int i : arr) {
			System.out.printf("%3d", i);
		}
		System.out.println();
	}
	
	static class ShortestPath {
		public int distence;
		public List<Integer> path;
	}
}

代码在原文代码的基础上通过增加 recordPathMap 来记录最短路径,最终打印最短路径距离和对应路劲信息。
在这里插入图片描述

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

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

相关文章

一方水土,一方气运

峰民风水悟语&#xff1a;“地灵人杰”&#xff0c;一方好水土&#xff0c;养育一方好人才。风水&#xff0c;就是一个地方的山水之气&#xff0c;会影响一个地方的人。正所谓&#xff1a;“山清水秀出美人&#xff0c;穷山恶水出刁民”就是这个理。 古人认为环境的能量磁场能控…

oracle19c容器数据库rman备份特性-----性能优化(三)

目录 冗余备份片 1.备份的时候指定 2.rman配置中设定 归档备份&#xff08;将备份集保留&#xff09; 二级备份&#xff08;将备份文件保留&#xff09; 1.备份闪回恢复区的恢复文件 2.备份所有恢复文件 recovery catalog database 1.創建recovery catalog 2.创建VPC…

cocos creator 如何绑定参数到编辑器

很多cocos creator同学不知道如何绑定组件属性到编辑器上&#xff0c;今天我们来教大家如何绑定 1: 基本数据属性绑定到编辑器 这个非常简单&#xff0c;模板是属性名字: 默认的值; Is_debug: false, speed: 100, 2: 系统组件类型与节点绑定到编辑器 属性名字: { type: 组件…

少儿编程 中国电子学会图形化编程2022年9月等级考试Scratch二级真题解析(选择题、判断题)

一、单选题(共25题&#xff0c;每题2分&#xff0c;共50分) 一、单选题(共25题&#xff0c;共50分) 1.数列&#xff1a;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;6&#xff0c;9&#xff0c;13&#xff0c;19&#xff0c;28&#xff0c;...的下一项是多少&#…

竞赛保研 基于深度学习的人脸性别年龄识别 - 图像识别 opencv

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…

第二百五十四回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何给图片添加阴影"相关的内容&#xff0c;本章回中将介绍自定义Radio组件.闲话休提&#xff0c;让我们一起Talk Flutter吧…

Spark 初级编程实践

什么是Spark? Spark是一个快速、通用、可扩展的大数据处理引擎,最初由加州大学伯克利分校的AMPLab开发。它提供了高级API,用于在大规模数据集上执行并行处理。Spark支持多种编程语言,包括Java、Scala、Python和R,因此被广泛应用于大数据分析和机器学习等领域。 一、目的 …

认识Linux指令之 “ 重定向” 符号

01.echo命令 在Linux中&#xff0c;我们可以使用echo命令打印 02. > 输出重定向 在111文件夹中我们只有dir文件夹和file.txt文件 用 echo > &#xff08;输出重定向&#xff09;我们可以将内容输入对应的文件中 也可以直接重定向 > >的作用 创建文件&#xff08…

【MATLAB】小波_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 小波-LSTM神经网络时序预测算法是一种结合了小波变换和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 小波变换是一种信号处理方法&#xff0c;能够将信号分解为…

.NET国产化改造探索(五)、结合Nginx并确保.NET应用程序自动启动

随着时代的发展以及近年来信创工作和…废话就不多说了&#xff0c;这个系列就是为.NET遇到国产化需求的一个闭坑系列。接下来&#xff0c;看操作。 上一篇介绍了如何在银河麒麟操作系统上安装Nginx&#xff0c;这篇文章详细介绍下在银河麒麟操作系统上&#xff0c;使用Nginx.N…

vue3 封装一个Tooltip 文字提示组件

效果图 默认展示icon图标&#xff0c;悬浮展示文字 如果slot有内容则展示对应内容 实现 用的是El-Tooltip组件 Element - The worlds most popular Vue UI framework 组件代码 <script setup lang"ts"> import { Icon } from /components/Icon import { ElTo…

《剑指offer》专项突破

第一章:整数 面试题1:整数除法 题目 输入两个int型整数,求它们除法的商,要求不得使用乘号’*‘、除号’/‘以及求余符号’%。当发生溢出时返回最大的整数值。假设除数不为0。例如,输入15和2,输出15/2的结果,即7。 参考代码 public int divide(int dividend, int di…

数字孪生与数据可视化大屏

什么是数字孪生 数字孪生技术是一种在现实世界中模拟虚拟世界的技术,它可以将物理世界中的各种事物、过程、行为等转化为虚拟世界中的数据模型,从而实现虚拟世界与现实世界的互动。数字孪生技术可以应用于能源管理、建筑能耗评估、设备全生命周期管理等领域,它可以帮助企业…

计算机体系结构流水线学习记录

一、知识点汇总 1.理想情况下&#xff0c;流水线能够实现 n 倍的吞吐率加速比&#xff08;n为流水线深度&#xff09;&#xff0c;但是流水线深度并非越大越好&#xff0c;因为流水线的深度会影响到性能和功耗之间的平衡。 2.RISC&#xff1a;Reduced Instruction Set Comput…

WPF真入门教程26--项目案例--欧姆龙PLC通讯工具

1、案例介绍 前面已经完成了25篇的文章介绍&#xff0c;概括起来就是从0开始&#xff0c;一步步熟悉了wpf的概念&#xff0c;UI布局控件&#xff0c;资源样式文件的使用&#xff0c;MVVM模式介绍&#xff0c;命令Command等内容&#xff0c;这节来完成一个实际的项目开发&#…

第57、58颗北斗导航卫星发射成功

第57、58颗北斗导航卫星发射成功&#xff01; 12月26日11时26分&#xff0c;我国在西昌卫星发射中心用长征三号乙运载火箭与远征一号上面级&#xff0c;成功发射第57、58颗北斗导航卫星。 这组卫星属中圆地球轨道卫星&#xff08;MEO卫星&#xff09;&#xff0c;是我国北斗三…

自动计算薪资-全优学堂

功能说明 全优学堂薪资模块则根据基础薪资、历史上课情况、课程销售情况自动计算员工薪资&#xff0c;帮助您更好地进行成本管理。系统根据教职工的排班情况、课时数和提成规则&#xff0c;自动计算教职工的薪资&#xff0c;大大减轻工资管理负担。 #1. 基础薪资配置 设置本…

ASP.NET中小型超市管理系统源码

ASP.NET中小型超市管理系统源码 超市管理系统是专门为中小型超市打造的管理系统&#xff0c;可以方便管理时更加准确清晰的查看商品信息&#xff0c; 仓库出售与进货的信息&#xff0c;还有每一个部门员工的信息&#xff0c;也更加直观的体现出每一阶段的商品销售情况&#xf…

python炒股自动化(0),申请券商API接口

上次发了量化交易接口的区别&#xff0c;发现很多人根本不知道券商提供的API交易接口&#xff0c;这里补充一篇&#xff0c;关于券商接口的介绍。 现在市面上可以给个人账户接入的股票交易接口&#xff0c;用的最多的也就是QMT和Ptrade&#xff0c;以前接入量化交易需要机构或…

【Gin实战教程】快速入门

Gin是一个轻量级的Web框架&#xff0c;使用Go语言开发。它具有高性能、易用性和灵活性的特点&#xff0c;是构建可扩展的Web应用程序的理想选择。 首先&#xff0c;Gin是一个高性能的框架。它基于Go语言的原生HTTP包进行开发&#xff0c;利用了Go语言的并发特性和协程模型&…