最短路径:迪杰斯特拉算法

news/2024/5/18 13:23:57/文章来源:https://blog.csdn.net/weixin_74261199/article/details/134116741
简介

        英文名Dijkstra

        作用:找到路中指定起点到指定终点的带权最短路径

核心步骤

        1)确定起点,终点

        2)从未走过的点中选取从起点到权值最小点作为中心点

        3)如果满足 起点到中心点权值 + 中心点到指定其他点的权值 < 起点到其他点的权值,

        即Weight[start] [center] +Weight [center] [other] < Weight [start] [center] ,

        简言之,有更短的路径就取更短的路

理论模拟

        以A为起点,D为终点,如图所示 径, 更新记录更短权值路径

 从未走过的点中选取权值最小点,即A作为中心点,标记A走过,更新起点到B、F、G的路径

 

从未走过的点中选取权值最小点,即B, 并且W:B->C + W:A->C = 12 + 10 < +oo ,更新起点A到C的路径和,

即W: A-> C =W: A-> B -> C =12+10 =22

 

 继续从未走过的点中选取权值最小点G, W: A -> E =+oo > W: A->G ->E =14+8 =22 ,

 更新W: A->E 为22

选取F, 由于W:A->F->E=16+2 =18 <22 更新 W: A-> E =18 ,

 选取E,由于W:A->E->D=18+4=22<+oo,则更新W: A->D =22

 选取C,无可更新点

 到达终点D! 最短路径为A->F->E->D ,最短路径和为22

 

Java代码实现
 顶点
//顶点类
public class Vertex {public String Number;  //顶点编号public List<Vertex>neighborVertexs;    //邻居顶点public Map<Vertex,Integer>weights;     //与邻居节点之间的权值public Vertex(String number) {this.Number = number;this.neighborVertexs=new LinkedList<>();this.weights=new HashMap<>();}
}
public class Edge {public Vertex start;public Vertex end;public Integer weight;public Edge(Vertex start, Vertex end, Integer weight) {this.start = start;this.end = end;this.weight = weight;}
}
最短路径返回结果
public class MinPathResult {public String minPathString;    //将最短路径拼接成字符串形式,如 A->B->Cpublic List<Vertex>minPathList; //将起点到终点的路径储存在List集合中public Integer minPathSum;  //记录起点到终点的最短路径和public MinPathResult(List<Vertex> minPathList, String minPathString,Integer minPathSum) {this.minPathString = minPathString;this.minPathList = minPathList;this.minPathSum=minPathSum;}@Overridepublic String toString() {return "Result{" +"minPathString:'" + minPathString +"  minPathSum:"+minPathSum+'}';}
}
Dijkstra算法的实现,适用于无向图
import java.util.*;
//适用于无向图
public class DijkstraOperator {private List<Vertex>vertexs;    //全部顶点private List<Edge>edges;        //所有边private Map<String,Vertex>vertexs_map;  //通过顶点编号找到顶点private final static Integer INF=Integer.MAX_VALUE;     //代表无穷大public DijkstraOperator(List<Vertex> vertexs, List<Edge> edges) {this.vertexs = vertexs;this.edges = edges;this.vertexs_map=new HashMap<>();//构建编号映射顶点for(Vertex v:vertexs){vertexs_map.put(v.Number,v);}//填充所有顶点的邻居以及权值for(int i=0;i<edges.size();i++){//填充起点的邻居,以及起点到终点的权值edges.get(i).start.neighborVertexs.add(edges.get(i).end);edges.get(i).start.weights.put(edges.get(i).end,edges.get(i).weight);//填充终点的邻居,以及终点到起点的权值edges.get(i).end.neighborVertexs.add(edges.get(i).start);edges.get(i).end.weights.put(edges.get(i).start,edges.get(i).weight);}}//获得从起点到终点之间的路径public MinPathResult getMinPath(String start, String end){//用哈希表标记某个顶点是否走过Map<Vertex,Boolean>visited=new HashMap<>();//用哈希表记录顶点的前驱Map<Vertex,Vertex>preVertex=new HashMap<>();//利用哈希表记录起点到任意一点的最短路径Map<Vertex,Integer>minPath=new HashMap<>();//初始化三个表for(int i=0;i<vertexs.size();i++){//初始化每一个点都未走过visited.put(vertexs.get(i),false);//初始化每个点的前驱都是自己preVertex.put(vertexs.get(i),vertexs.get(i));//初始化起点到任意两个点之间的最短路径都是无穷大minPath.put(vertexs.get(i),INF);}Vertex startVertex=vertexs_map.get(start);Vertex endVertex=vertexs_map.get(end);//填充存在的路径for(int i=0;i<startVertex.neighborVertexs.size();i++){//设置起点与邻居节点之间的权值minPath.put(startVertex.neighborVertexs.get(i),startVertex.weights.get(startVertex.neighborVertexs.get(i)));//设置点前驱preVertex.put(startVertex.neighborVertexs.get(i),startVertex);}//自己到自己的距离为0minPath.put(startVertex,0);Vertex curVertex=null;//一直寻路,直到找到终点while(curVertex!=endVertex){Integer minWeight=Integer.MAX_VALUE;curVertex=null;//能看到的点之间选取距离最小的那个,且这个点并没有走过for(Vertex v:minPath.keySet()){if(!visited.get(v)&&minPath.get(v)<minWeight){//切换中心点curVertex=v;//更新最小权值minWeight=minPath.get(v);}}//如果找不到下一个中心点,说明从起点根本到达不来终点if(curVertex==null)return null;//标记选取点visited.put(curVertex,true);//更新权值for(int i=0;i<curVertex.neighborVertexs.size();i++){//邻居节点Vertex neighborVertex=curVertex.neighborVertexs.get(i);//计算起点到邻居节点之间新的权值int newWeight=minPath.get(curVertex)+curVertex.weights.get(neighborVertex);//找到能移动的点,如果转折之后距离更短,则记录更短的距离if(visited.get(neighborVertex)==false&&newWeight<minPath.get(neighborVertex)){//记录更短距离minPath.put(neighborVertex,newWeight);//记录邻居节点的前驱preVertex.put(neighborVertex,curVertex);}}}//起点到终点之间的最短路径LinkedList<Vertex>targetPath=new LinkedList<>();for(Vertex curVer=endVertex;curVer!=startVertex;curVer=preVertex.get(curVer)){targetPath.addFirst(curVer);}targetPath.addFirst(startVertex);//拼接最短路径StringBuffer minPathStringBuffer=new StringBuffer();Integer pathSum=0;for(int i=0;i< targetPath.size();i++){minPathStringBuffer.append(targetPath.get(i).Number);if(i!= targetPath.size()-1){pathSum=pathSum+targetPath.get(i).weights.get(targetPath.get(i+1));minPathStringBuffer.append("->");}}return new MinPathResult(targetPath, minPathStringBuffer.toString(),pathSum);}
}
测试函数
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner=new Scanner(System.in);List<Vertex>vertexs=new LinkedList<>();List<Edge>edges=new LinkedList<>();System.out.println("请输入顶点的数量:");Integer vexcnt= scanner.nextInt();System.out.println("请输入这些顶点编号:");for(int i=0;i<vexcnt;i++){vertexs.add(new Vertex(scanner.next()));}System.out.println("请输入边的数量:");Integer edgecnt= scanner.nextInt();System.out.println("请输入这些边的端点编号和权值:");for(int i=0;i<edgecnt;i++){String number1= scanner.next();String number2= scanner.next();Integer weight= scanner.nextInt();Vertex v1=null;Vertex v2=null;for(int j=0;j<vertexs.size();j++){if(vertexs.get(j).Number.equals(number1))v1=vertexs.get(j);if(vertexs.get(j).Number.equals(number2))v2=vertexs.get(j);}edges.add(new Edge(v1,v2,weight));}//定义迪杰斯特拉操作类DijkstraOperator dijkstra=new DijkstraOperator(vertexs,edges);//获取任意两点之间的最短路径结果集List<MinPathResult>minPathResults=new ArrayList<>();for(int i=0;i< vertexs.size();i++){for(int j=i+1;j< vertexs.size();j++){minPathResults.add(dijkstra.getMinPath(vertexs.get(i).Number,vertexs.get(j).Number));System.out.println(minPathResults.get(minPathResults.size()-1));}}}
}
测试输入与输出结果
//输入部分
请输入顶点的数量:
7
请输入这些顶点编号:
A B C D E F G
请输入边的数量:
12
请输入这些边的端点编号和权值:
A B 12
A F 16
A G 14
B C 10
B F 7
G F 9
G E 8
F C 6
F E 2
C D 3
C E 5
E D 4//输出部分
Result{minPathString:'A->B  minPathSum:12}
Result{minPathString:'A->B->C  minPathSum:22}
Result{minPathString:'A->F->E->D  minPathSum:22}
Result{minPathString:'A->F->E  minPathSum:18}
Result{minPathString:'A->F  minPathSum:16}
Result{minPathString:'A->G  minPathSum:14}
Result{minPathString:'B->C  minPathSum:10}
Result{minPathString:'B->F->E->D  minPathSum:13}
Result{minPathString:'B->F->E  minPathSum:9}
Result{minPathString:'B->F  minPathSum:7}
Result{minPathString:'B->F->G  minPathSum:16}
Result{minPathString:'C->D  minPathSum:3}
Result{minPathString:'C->E  minPathSum:5}
Result{minPathString:'C->F  minPathSum:6}
Result{minPathString:'C->E->G  minPathSum:13}
Result{minPathString:'D->E  minPathSum:4}
Result{minPathString:'D->E->F  minPathSum:6}
Result{minPathString:'D->E->G  minPathSum:12}
Result{minPathString:'E->F  minPathSum:2}
Result{minPathString:'E->G  minPathSum:8}
Result{minPathString:'F->G  minPathSum:9}进程已结束,退出代码为 0

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32单片机智能小车一PWM方式实现小车调速和转向

目录 1. 电机模块开发 2. 让小车动起来 3. 串口控制小车方向 4. 如何进行小车PWM调速 5. PWM方式实现小车转向 1. 电机模块开发 L9110s概述 接通VCC&#xff0c;GND 模块电源指示灯亮&#xff0c; 以下资料来源官方&#xff0c;具体根据实际调试 IA1输入高电平&#xff…

BUUCTF qr 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 这是一个二维码&#xff0c;谁用谁知道&#xff01; 密文&#xff1a; 下载附件&#xff0c;得到一张二维码图片。 解题思路&#xff1a; 1、这是一道签到题&#xff0c;扫描二维码得到flag。 flag&#xff1a;…

外汇天眼:在2023年Expo上探索金融科技的未来!

从2020年初至2022年年底&#xff0c;全球范围内爆发的新冠疫情蔓延&#xff0c;对各国经济造成了严重冲击&#xff0c;导致贸易活动几近停滞&#xff0c;国际人员流动受限&#xff0c;产业链陷入危机。为应对这一局面&#xff0c;美欧经济体采取了前所未有的扩张性财政和货币政…

高效分割分段视频:提升您的视频剪辑能力

在数字媒体时代&#xff0c;视频剪辑已经成为一项重要的技能。无论是制作个人影片、广告还是其他类型的视频内容&#xff0c;掌握高效的视频剪辑技巧都是必不可少的。本文将介绍如何引用云炫AI智剪高效地分割和分段视频&#xff0c;以提升您的视频剪辑能力。以下是详细的操作步…

设计模式—创建型模式之原型模式

设计模式—创建型模式之原型模式 原型模式&#xff08;Prototype Pattern&#xff09;用于创建重复的对象&#xff0c;同时又能保证性能。 本体给外部提供一个克隆体进行使用。 比如我们做一个SjdwzMybatis&#xff0c;用来操作数据库&#xff0c;从数据库里面查出很多记录&…

半导体产线应用Power Link 转EtherCAT协议网关数字化转型

随着数字化转型的推进&#xff0c;越来越多的企业开始意识到数字化转型的重要性&#xff0c;并将其作为发展战略的关键之一。半导体产线作为一个高度自动化的生产系统&#xff0c;自然也需要数字化转型来提高效率、降低成本和提高质量。Power Link 转EtherCAT协议网关是半导体产…

RISC-V IDE MRS无感远程协助模块详解

RISC-V IDE MRS无感远程协助模块详解 一、说明 1.1 概述 针对RISC-V/ARM等内核MCU的嵌入式集成开发环境MRS(MounRiver Studio)从V1.90版本开始内置无感远程协助模块&#xff08;Sensorless Remote Assistant Module&#xff0c;以下简称SRA模块&#xff09;。SRA模块是一款支…

MAC缓解WebUI提示词反推

当前环境信息&#xff1a; 在mac上安装好stable diffusion后&#xff0c;能做图片生成了之后&#xff0c;遇到一些图片需要做提示词反推&#xff0c;这个时候需要下载一个插件&#xff0c;参考&#xff1a; https://gitcode.net/ranting8323/stable-diffusion-webui-wd14-tagg…

0基础学习VR全景平台篇第114篇:全景图优化和输出 - PTGui Pro教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 前情回顾&#xff1a;之前&#xff0c;我们详细介绍了如何用编辑器、控制点、垂直线等功能优化错位和矫正水平&#xff0c;然而这些调整不会马上生效。 我们需要在【优化】选项卡…

python爬虫selenium和ddddocr使用

python爬虫selenium和ddddocr使用 selenium使用 selenium实际上是web自动化测试工具&#xff0c;能够通过代码完全模拟人使用浏览器自动访问目标站点并操作来进行web测试。 通过pythonselenium结合来实现爬虫十分巧妙。 由于是模拟人的点击来操作&#xff0c;所以实际上被反…

UE4 体积云制作 学习笔记

首先Noise本来就是一张噪点图 云的扰动不能太大&#xff0c;将Scale调小&#xff0c;并将InputMin调整为0 形成这样一张扰动图 扰动需要根据材质在世界的位置进行调整&#xff0c;所以Position需要加上WorldPosition 材质在不同世界位置&#xff0c;噪点不同 除以一个数&#…

【Jenkins】新建任务FAQ

问题1. 源码管理处填入Repository URL&#xff0c;报错&#xff1a;无法连接仓库&#xff1a;Error performing git command: ls-remote -h https://github.com/txy2023/GolangLearning.git HEAD 原因&#xff1a; jenkins全局工具配置里默认没有添加git的路径&#xff0c;如果…

【Redis】认识Redis-特点特性应用场景对比MySQL重要文件及作用

文章目录 认识redisredis的主要特点redis的特性&#xff08;优点&#xff09;redis是单线程模型&#xff0c;为什么效率这么高&#xff0c;访问速度这么快redis应用场景redis不可以做什么MySQL和Redis对比启动RedisRedis客户端Redis重要文件及作用 认识redis redis里面相关的小…

SCNet:自校正卷积网络(附代码)

论文地址&#xff1a;https://mftp.mmcheng.net/Papers/20cvprSCNet.pdf 代码地址&#xff1a;https://github.com/MCG-NKU/SCNet 1.是什么&#xff1f; SCNet是一种卷积神经网络&#xff0c;它使用自校准卷积&#xff08;Self-Calibrated Convolutions&#xff09;来增强子…

web:[网鼎杯 2020 青龙组]AreUSerialz

题目 点进题目发现 需要进行代码审计 function __destruct() {if($this->op "2")$this->op "1";$this->content "";$this->process();}这里有__destruct()函数&#xff0c;在对象销毁时自动调用&#xff0c;根据$op属性的值进行…

一个基于Excel模板快速生成Excel文档的小工具

介绍 DocumentGenerator是一个Excel快速生成工具&#xff0c;目标以后还能实现Word、pdf等的文件的生成。该程序独立运行&#xff0c;可通过HTTP接口调用其生成接口。 典型使用场景为如下&#xff1a; 使用者编写模板文件使用者准备模板文件的填充JSON数据内容使用者通过网络…

【LVS实战】02 搭建一个LVS-NAT实验

一、网络结构 用虚拟机搭建如下的几台机器&#xff0c;并配置如下的ip 关于虚拟机网卡和网络的配置&#xff0c;可以参考 iptables章节&#xff0c;05节&#xff1a;网络转发实验 主机A模拟外网的机器 B为负载均衡的机器 C和D为 RealServer 二、C和D主机的网关设置 C和D机…

Qt 重写QSlider简单实现滑动解锁控件(指定百分比回弹效果)

组件效果图: 应用场景: 用于滑动解锁相关场景,Qt的控件鼠标监听机制对于嵌入式设备GUI可触摸屏依旧可用。 实现方式: 主要是通过继承QSlider以及搭配使用QStyleOptionSlider来实现效果。 注意细则: QStyleOptionSlider是用于定制空白区域是否可移动滑块,根据需求可…

[Linux]线程池

[Linux]线程池 文章目录 [Linux]线程池线程池的概念线程池的优点线程池的应用场景线程池的实现 线程池的概念 线程池是一种线程使用模式。线程池是一种特殊的生产消费模型&#xff0c;用户作为生产者&#xff0c;线程池作为消费者和缓冲区。 线程过多会带来调度开销&#xff0c…

第16期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…