算法练习(19)-单源最短路径dijkstra算法

如上图,先初始化1个图,每条边上的红色数字为路径权重:(Node,Edge的定义参见算法练习(17)-图的广度优先遍历/深度优先遍历)
Graph init() {
List<Node> nodes = new ArrayList<>();
List<Edge> edges = new ArrayList<>();
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
nodes.add(n1);
nodes.add(n2);
nodes.add(n3);
nodes.add(n4);
nodes.add(n5);
Edge e_1_2 = new Edge(1, n1, n2);
Edge e_2_1 = new Edge(1, n2, n1);
Edge e_1_3 = new Edge(7, n1, n3);
Edge e_3_1 = new Edge(7, n3, n1);
Edge e_1_4 = new Edge(8, n1, n4);
Edge e_4_1 = new Edge(8, n4, n1);
Edge e_2_3 = new Edge(5, n2, n3);
Edge e_3_2 = new Edge(5, n3, n2);
Edge e_3_4 = new Edge(10, n3, n4);
Edge e_4_3 = new Edge(10, n4, n3);
Edge e_2_5 = new Edge(20, n2, n5);
Edge e_5_2 = new Edge(20, n5, n2);
Edge e_5_4 = new Edge(9, n5, n4);
Edge e_4_5 = new Edge(9, n4, n5);
Edge e_3_5 = new Edge(6, n3, n5);
Edge e_5_3 = new Edge(6, n5, n3);
n1.edges.add(e_1_2);
n1.edges.add(e_1_3);
n1.edges.add(e_1_4);
n2.edges.add(e_2_1);
n2.edges.add(e_2_3);
n2.edges.add(e_2_5);
n3.edges.add(e_3_1);
n3.edges.add(e_3_2);
n3.edges.add(e_3_4);
n3.edges.add(e_3_5);
n4.edges.add(e_4_1);
n4.edges.add(e_4_3);
n4.edges.add(e_4_5);
n5.edges.add(e_5_2);
n5.edges.add(e_5_3);
n5.edges.add(e_5_4);
edges.add(e_1_2);
edges.add(e_2_1);
edges.add(e_1_3);
edges.add(e_3_1);
edges.add(e_1_4);
edges.add(e_4_1);
edges.add(e_2_3);
edges.add(e_3_2);
edges.add(e_3_4);
edges.add(e_4_3);
edges.add(e_2_5);
edges.add(e_5_2);
edges.add(e_5_4);
edges.add(e_4_5);
edges.add(e_3_5);
edges.add(e_5_3);
Graph g = new Graph(nodes, edges);
return g;
}
假设从节点1出发,到达其它节点的最短路径(权重)为:
| 出发点 | 目的地 | 最短路径(权重)和 | 全路径 |
| 1 | 1 | 0 | 1->1 |
| 1 | 2 | 1 | 1->2 |
| 1 | 3 | 1+5 | 1->2->3 |
| 1 | 4 | 8 | 1->4 |
| 1 | 5 | 1+5+6 | 1->2->3->5 |
package advanced;
import java.util.*;
public class GraphTest {
Graph init() {
... 略...
}
/**
* dijkstra算法
* @param head
* @return
*/
Map<Node, Integer> dijkstra(Node head) {
/**
* 用于保存从head到其它node的距离总和
* 不在该map中节点,表示还没走到,默认距离为正无穷
*/
Map<Node, Integer> distanceMap = new HashMap<>();
//首节点:从head到head的距离为0
distanceMap.put(head, 0);
//已经计算过的节点
Set<Node> selectedNodes = new HashSet<>();
//从出发点,找出距离最短的节点
Node minNode = getMinDistanceNode(distanceMap, selectedNodes);
while (minNode != null) {
int distance = distanceMap.get(minNode);
for (Edge edge : minNode.edges) {
Node toNode = edge.to;
if (!distanceMap.containsKey(toNode)) {
distanceMap.put(toNode, distance + edge.weight);
}
//取最短距离,更新distanceMap
distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
}
//已计算过的节点,做下标识
selectedNodes.add(minNode);
minNode = getMinDistanceNode(distanceMap, selectedNodes);
}
return distanceMap;
}
/**
* 从distanceMap中找出最小距离的节点(已计算过的节点忽略)
* @param distanceMap
* @param touchedNodes
* @return
*/
Node getMinDistanceNode(Map<Node, Integer> distanceMap,
Set<Node> touchedNodes) {
Node minNode = null;
int minDistance = Integer.MAX_VALUE;
for (Map.Entry<Node, Integer> entry : distanceMap.entrySet()) {
Node node = entry.getKey();
int distance = entry.getValue();
if (!touchedNodes.contains(node) && distance < minDistance) {
minNode = node;
minDistance = distance;
}
}
return minNode;
}
public static void main(String[] args) {
GraphTest t = new GraphTest();
Graph g = t.init();
Map<Node, Integer> dijkstra = t.dijkstra(g.nodes.get(0));
System.out.println(dijkstra);
}
}
输出:
{3=6, 4=8, 1=0, 5=12, 2=1}
注意:这个算法,有一个前提条件,如果图中有环,环上的路径合不能为负值,否则会在环里转来转去,每转一圈,路径合更小,一直循环,转不出来。

如上图,如果从1出发,要计算到节点2的最短路径,每转一圈,总路径反而更短。这种情况下,可以将所有边上的权重加“最大负权重”,将所有边上的权重变成非负值。

算法练习(19)-单源最短路径dijkstra算法的更多相关文章
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- 单源最短路径——dijkstra算法
dijkstra算法与prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...
- 单源最短路径 dijkstra算法实现
本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图.而且连通,有向图,不连通图的做法相似. 算法简述: 首先确定"单源"的源.假设是第0个顶点. 维护三个数组 ...
- 单源最短路径——Dijkstra算法学习
每次都以为自己理解了Dijkstra这个算法,但是过没多久又忘记了,这应该是第4.5次重温这个算法了. 这次是看的胡鹏的<地理信息系统>,看完之后突然意识到用数学公式表示算法流程是如此的好 ...
- 单源最短路径-Dijkstra算法
1.算法标签 贪心 2.算法描述 具体的算法描述网上有好多,我觉得莫过于直接wiki,只说明一些我之前比较迷惑的. 对于Dijkstra算法,最重要的是维护以下几个数据结构: 顶点集合S : 表示已经 ...
- [数据结构与算法-15]单源最短路径(Dijkstra+SPFA)
单源最短路径 问题描述 分别求出从起点到其他所有点的最短路径,这次主要介绍两种算法,Dijkstra和SPFA.若无负权优先Dijkstra算法,存在负权选择SPFA算法. Dijkstra算法 非负 ...
- 【算法导论】单源最短路径之Dijkstra算法
Dijkstra算法解决了有向图上带正权值的单源最短路径问题,其运行时间要比Bellman-Ford算法低,但适用范围比Bellman-Ford算法窄. 迪杰斯特拉提出的按路径长度递增次序来产生源点到 ...
- 【算法导论】单源最短路径之Bellman-Ford算法
单源最短路径指的是从一个顶点到其它顶点的具有最小权值的路径.我们之前提到的广度优先搜索算法就是一种无权图上执行的最短路径算法,即在所有的边都具有单位权值的图的一种算法.单源最短路径算法可以解决图中任意 ...
- 经典贪心算法(哈夫曼算法,Dijstra单源最短路径算法,最小费用最大流)
哈夫曼编码与哈夫曼算法 哈弗曼编码的目的是,如何用更短的bit来编码数据. 通过变长编码压缩编码长度.我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit.但在很多情况下,数 ...
- matlab练习程序(单源最短路径Dijkstra)
图的相关算法也算是自己的一个软肋了,当年没选修图论也是一大遗憾. 图像处理中,也有使用图论算法作为基础的相关算法,比如图割,这个算法就需要求最大流.最小割.所以熟悉一下图论算法对于图像处理还是很有帮助 ...
随机推荐
- spring boot迁移计划 第Ⅰ章 --chapter 1. rust hyper 结合rust nacos-client开发nacos网关 part ③ toml配置文件
1. toml依赖 toml = "0.8" 2. 代码 由于项目还未完成,部分配置(如数据库等)还未增加,后续更新增加 use log::info; use serde::Des ...
- SgLang代码细读-2.forward过程
SgLang代码细读-2.forward过程 总览 Forward的主要过程围绕着 run_batch->TPModelWorker->ModelRunner->Model-> ...
- 【多线程】Java多线程与并发编程全解析
Java多线程与并发编程全解析 多线程编程是Java中最具挑战性的部分之一,它能够显著提升应用程序的性能和响应能力.本文将全面解析Java多线程与并发编程的核心概念.线程安全机制以及JUC工具类的使用 ...
- 在java中动态执行js代码
说明 在jdk11就标注了要取消NashornScriptEngineFactory类,在jdk17正式移除,所以在17上得加入pom依赖 <dependency> <groupId ...
- Kubernetes存储-Ceph存储
Kubernetes存储-Ceph存储 原文链接:https://www.qikqiak.com/k8strain/storage/ceph/#_11 简介 Ceph 是一个统一的分布式存储系统,提供 ...
- Benchmark论文解读:Evaluating the Ripple Effects of Knowledge Editing in Language Models
论文发表于自然语言处理顶刊TACL-2024(原文链接).目前模型编辑方法的评估主要集中在测试单个事实是否被成功注入,以及模型对其它事实的预测是否没有改变.作者认为这样的评估模式有限,因为注入一个 ...
- EasyMR 基于国产化信创的适配实践技术详解
国产化信创,即采用国产信息技术产品和服务,构建自主可控的信息技术体系.近年来,随着国家对网络安全和信息安全的重视程度不断提高,国产化信创已经成为国家战略的重要组成部分,并呈现出以下大趋势: ● 政策驱 ...
- 数栈技术文章分享:你居然是这样的initialValue
先说一下写着篇文章的契机,是因为回显,复杂表单的回显,让我觉得我对initialValue这个属性是有误解的. 一.initialValue的出处和定义 initialValue的出处: AntDes ...
- Linux 上安装配置 VNC Server
一:简介 VNC (Virtual Network Console),即 虚拟网络控制台.它是一款优秀的远程控制工具软件,而且是基于 UNIX 和 Linux 操作系统的免费开源的. 二:VNC 服务 ...
- 【闲话 No.3】 并查集相关
命に嫌われている. 小唐话 感觉有的时候已经无法与人正常交流,净做唐事.说些唐话了.或许是我无法准确猜到别人喜欢什么吧. 不过还是自己心底一点 joker 之心/私心作祟吧. 感觉我有时做的唐事真的挺 ...