图的最短路径算法:原理与实现

图的最短路径算法:原理与实现

在图论中,最短路径算法用于找到图中从一个顶点到另一个顶点的最短路径。常见的最短路径算法包括Dijkstra算法、Bellman-Ford算法和Floyd-Warshall算法。以下是每个算法的详细讲解及其Java实现。

1. Dijkstra算法

原理
Dijkstra算法是一种贪心算法,适用于无负权边的图。它通过逐步扩展从源节点到其他节点的最短路径,确保每次选择的路径都是当前最短的路径。

步骤

  1. 初始化:将源节点的距离设为0,其余节点的距离设为无穷大。
  2. 选择未处理节点中距离最小的节点作为当前节点。
  3. 更新当前节点的邻居节点的距离,如果通过当前节点到邻居节点的路径比原有路径更短,则更新邻居节点的距离。
  4. 标记当前节点为已处理。
  5. 重复步骤2-4,直到所有节点都被处理。

Java实现

import java.util.*;public class Dijkstra {public static Map<String, Integer> dijkstra(Map<String, Map<String, Integer>> graph, String start) {Map<String, Integer> distances = new HashMap<>();for (String node : graph.keySet()) {distances.put(node, Integer.MAX_VALUE);}distances.put(start, 0);PriorityQueue<Map.Entry<String, Integer>> priorityQueue = new PriorityQueue<>(Map.Entry.comparingByValue());priorityQueue.add(new AbstractMap.SimpleEntry<>(start, 0));while (!priorityQueue.isEmpty()) {Map.Entry<String, Integer> current = priorityQueue.poll();String currentNode = current.getKey();int currentDistance = current.getValue();if (currentDistance > distances.get(currentNode)) {continue;}Map<String, Integer> neighbors = graph.get(currentNode);for (Map.Entry<String, Integer> neighbor : neighbors.entrySet()) {int distance = currentDistance + neighbor.getValue();if (distance < distances.get(neighbor.getKey())) {distances.put(neighbor.getKey(), distance);priorityQueue.add(new AbstractMap.SimpleEntry<>(neighbor.getKey(), distance));}}}return distances;}public static void main(String[] args) {Map<String, Map<String, Integer>> graph = new HashMap<>();graph.put("A", Map.of("B", 1, "C", 4));graph.put("B", Map.of("A", 1, "C", 2, "D", 5));graph.put("C", Map.of("A", 4, "B", 2, "D", 1));graph.put("D", Map.of("B", 5, "C", 1));Map<String, Integer> distances = dijkstra(graph, "A");System.out.println(distances);}
}
2. Bellman-Ford算法

原理
Bellman-Ford算法适用于含有负权边的图,并且可以检测负权环。它通过逐步松弛边缘,确保每次选择的路径都是当前最短的路径。

步骤

  1. 初始化:将源节点的距离设为0,其余节点的距离设为无穷大。
  2. 重复图中边数 - 1 次:
    • 对每一条边 (u, v),如果通过 u 到 v 的距离比当前距离短,则更新距离。
  3. 再次检查所有边,如果仍然能找到更短路径,则说明存在负权环。

Java实现

import java.util.HashMap;
import java.util.Map;public class BellmanFord {public static Map<String, Integer> bellmanFord(Map<String, Map<String, Integer>> graph, String start) throws Exception {Map<String, Integer> distances = new HashMap<>();for (String node : graph.keySet()) {distances.put(node, Integer.MAX_VALUE);}distances.put(start, 0);for (int i = 0; i < graph.size() - 1; i++) {for (String node : graph.keySet()) {for (Map.Entry<String, Integer> neighbor : graph.get(node).entrySet()) {int newDist = distances.get(node) + neighbor.getValue();if (newDist < distances.get(neighbor.getKey())) {distances.put(neighbor.getKey(), newDist);}}}}for (String node : graph.keySet()) {for (Map.Entry<String, Integer> neighbor : graph.get(node).entrySet()) {if (distances.get(node) + neighbor.getValue() < distances.get(neighbor.getKey())) {throw new Exception("Graph contains a negative weight cycle");}}}return distances;}public static void main(String[] args) {Map<String, Map<String, Integer>> graph = new HashMap<>();graph.put("A", Map.of("B", 1, "C", 4));graph.put("B", Map.of("A", 1, "C", 2, "D", 5));graph.put("C", Map.of("A", 4, "B", 2, "D", 1));graph.put("D", Map.of("B", 5, "C", 1));try {Map<String, Integer> distances = bellmanFord(graph, "A");System.out.println(distances);} catch (Exception e) {e.printStackTrace();}}
}
3. Floyd-Warshall算法

原理
Floyd-Warshall算法用于计算所有节点对之间的最短路径,适用于加权图,包括负权边。它通过逐步扩展中间节点,确保每次选择的路径都是当前最短的路径。

步骤

  1. 初始化:将每个节点到自身的距离设为0,其余节点之间的距离设为无穷大(如果没有直接边)。
  2. 对每个节点 k 作为中间节点,更新所有节点对之间的距离:
    • 对每一对节点 (i, j),通过 k 更新距离,如果 i 到 k 再到 j 的距离比直接距离短,则更新距离。

Java实现

import java.util.HashMap;
import java.util.Map;public class FloydWarshall {public static Map<String, Map<String, Integer>> floydWarshall(Map<String, Map<String, Integer>> graph) {Map<String, Map<String, Integer>> distances = new HashMap<>();for (String node : graph.keySet()) {distances.put(node, new HashMap<>());for (String target : graph.keySet()) {if (node.equals(target)) {distances.get(node).put(target, 0);} else {distances.get(node).put(target, graph.get(node).getOrDefault(target, Integer.MAX_VALUE));}}}for (String k : graph.keySet()) {for (String i : graph.keySet()) {for (String j : graph.keySet()) {if (distances.get(i).get(k) != Integer.MAX_VALUE && distances.get(k).get(j) != Integer.MAX_VALUE) {int newDist = distances.get(i).get(k) + distances.get(k).get(j);if (newDist < distances.get(i).get(j)) {distances.get(i).put(j, newDist);}}}}}return distances;}public static void main(String[] args) {Map<String, Map<String, Integer>> graph = new HashMap<>();graph.put("A", Map.of("B", 1, "C", 4));graph.put("B", Map.of("A", 1, "C", 2, "D", 5));graph.put("C", Map.of("A", 4, "B", 2, "D", 1));graph.put("D", Map.of("B", 5, "C", 1));Map<String, Map<String, Integer>> distances = floydWarshall(graph);System.out.println(distances);}
}

结论

  • Dijkstra算法:适用于没有负权边的图,时间复杂度为O(V^2)(使用邻接矩阵)或O(E + V log V)(使用优先队列和邻接表)。
  • Bellman-Ford算法:适用于含有负权边的图,可以检测负权环,时间复杂度为O(VE)。
  • Floyd-Warshall算法:用于计算所有节点对之间的最短路径,时间复杂度为O(V^3)。

合适的算法取决于图的特性(是否含有负权边、图的规模等)和具体的应用需求。

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

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

相关文章

Android (已解决)Execution failed for task ‘:app:lint‘

文章目录 一、错误原因二、解决方法 一、错误原因 这个错误信息表示在执行 Lint 检查时发现了错误&#xff0c;导致构建过程被中断。Lint 是一个用于检测 Android 项目中潜在问题的工具&#xff0c;比如性能、安全性、可用性等方面的问题。当Lint检查到严重错误时&#xff0c;…

RabbitMQ如何保证消息可靠

解决办法&#xff1a; 1、做好消息确认机制&#xff08;pulisher、consumer[手动ACK]&#xff09; 2、每一个发送的消息都在数据库做好记录。定期将失败的消息再次发送一遍 消息确认机制&#xff1a; 生产者确认模式&#xff1a;确认消息是否发送到broker&#xff0c;失败…

20240627(26.4) 财经要闻汇总

重点关注 ► 发改委&#xff1a;我国金融规模体系已经很大了&#xff0c;但融资结构还有待改善。耐心资本的培育对于促进我国创业投资高质量发展和实现高水平科技自立自强至关重要。除了充分尊重市场规律以外&#xff0c;政府这只“有形的手”也可以发挥重要作用&#xff0c;引…

【FPGA-常见问题及解决方案】

1、VIVADO的License无法加载&#xff1a;license文件必须在英文路径&#xff1b; 2、例程代码路径不能过长&#xff0c;也不允许有中文路径&#xff01;&#xff01;&#xff01; 3、明明加载了license&#xff0c;license也正确&#xff0c;例程无法完成综合&#xff1a;这种情…

“北京到底有谁在啊”影视APP开发,解锁最简单的快乐

随着电视剧《玫瑰的故事》在腾讯视频APP热播&#xff0c;APP也增加了很多热度&#xff0c;一款丰富的影视APP&#xff0c;无论是热门大片、经典影视剧、还是最新综艺节目&#xff0c;能畅享无限精彩的影视内容&#xff01; 开发影视APP&#xff0c;需要专业的技术服务商来解决…

1500平方米气膜羽毛球馆的造价分析—轻空间

随着全民健身热潮的兴起&#xff0c;气膜羽毛球馆因其良好的空气质量、恒温恒湿的环境和快捷的建设速度&#xff0c;受到了越来越多人的欢迎。建造一个1500平方米的气膜羽毛球馆涉及多个方面的费用&#xff0c;包括场地准备、设备材料、安装施工、配套设施等。轻空间将详细分析…

【设计模式】【结构型7-1】【代理模式】【动态代理】【静态代理】

文章目录 代理模式静态代理第一步 创建接口第二步 创建需要代理的对象第三步 创建代理对象 使用 动态代理jdk动态代理cjlib动态代理 代理模式 代理 是结构型 通过继承&#xff0c;或者实现相同的接口来进行增强和监控 经典的使用 spring aop&#xff0c;mybatis dao层 静态代…

数据清洗的艺术:Python中的Pandas妙用

1. 引言 凡事总须研究&#xff0c;才会明白。在这信息泛滥的时代&#xff0c;数据如同一片混沌的荒原&#xff0c;若不经雕琢&#xff0c;便难以显现其真面目。而对于程序员而言&#xff0c;数据清洗的过程&#xff0c;正是从混沌到秩序的一次次锤炼。 2. 数据清洗的必要性 …

Docker制作Python项目镜像

Docker制作Python项目镜像 背景DockerfileDockerfile内容阐释 制作镜像迁移镜像启动容器 背景 在离线环境部署Python项目&#xff0c;出了需要安装对应版本的Python环境&#xff0c;还需要在项目启动前下载项目所需要的依赖。如果后面的迭代依赖有所更新&#xff0c;在离线环境…

AutoEncoder简介

1.介绍 作为一种无监督或者自监督算法&#xff0c;自编码器本质上是一种数据压缩算法。 编码器&#xff1a; 输入图像&#xff08;在这个例子中是一个28x28像素的数字“9”&#xff09;首先被输入到编码器中。编码器的任务是将这个输入压缩成一个更小的、密集的表示形式&…

docker配置国内镜像加速器

1、搜索阿里云 2、搜索容器镜像服务 点击管理控制台 配置镜像加速器

跌幅高达10.2分!32本Top,Elsevier旗下在检SSCI期刊(2024年6月影响因子更新版)

本周投稿推荐 SSCI • 1区&#xff0c;4.0-5.0&#xff08;无需返修&#xff0c;提交可录&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09; CNKI • 7天录用-检索&#xff08;急录友好&#xff09; SCI&EI • 4区生物医学类&#xff0c;0.1-0.5&…

【AI应用探讨】—朴素贝叶斯应用场景

目录 文本分类 推荐系统 信息检索 生物信息学 金融领域 医疗诊断 其他领域 文本分类 垃圾邮件过滤&#xff1a;朴素贝叶斯被广泛用于垃圾邮件过滤任务&#xff0c;通过邮件中的文本内容来识别是否为垃圾邮件。例如&#xff0c;它可以基于邮件中出现的单词或短语的概率来…

【单片机毕业设计选题24031】-基于STM32的智能手环设计

系统功能: 使用12864OLED液晶屏显示当前的步数&#xff0c;温度值&#xff0c;心率和报警值&#xff0c;单位是心率/分钟设置步长&#xff0c;测量里程&#xff1b;可以设置温度心率的上下限报警值&#xff0c;设置、加、减&#xff1b;用红外传感器XL01实现心率的测量&#x…

win10免安装配置MySQL8.4.0

注&#xff1a;此教程基于win10 22H2 版本 1、下载最新版本MySQL压缩包 下载链接&#xff1a;MySQL官网下载地址 点击第二行的 ZIP Archive 后面的Download&#xff08;当前时间2024-06-19最新版本是8.4.0&#xff09; 2、解压并添加配置文件 下载完毕后&#xff0c;解压缩…

新能源汽车电机分类及工作原理

一、直流电机与交流电机 电机是一种将电能转换为机械能的设备&#xff0c;常见的有直流电机和交流电机两种类型。下面简要介绍它们的原理&#xff1a; 直流电机&#xff08;DC Motor&#xff09;: 原理: 直流电机的工作原理基于洛伦兹力定律&#xff0c;即电流通过导线时&…

ABAP隐藏选择屏幕F8执行按钮的两种方式

在选择屏幕上画PUSHBUTTON的时候&#xff0c;通常不需要左上角的执行按钮&#xff0c;所以需要隐藏掉&#xff0c;两种方式可以实现&#xff0c;都需要在INITIALZATION或者AT SELECTION-SCREEN OUTPUT事件中完成。 方式1&#xff1a; at selection-screen output.perform ins…

解决 Pyecharts 在 jupyter Lab 上运行图片空白问题!

文章目录 &#x1f3f3;️‍&#x1f308; 1 提前声明 JUPYTER_LAB&#x1f3f3;️‍&#x1f308; 2 load_javascript(&#xff09;&#x1f3f3;️‍&#x1f308; 3 render_notebook()&#x1f3f3;️‍&#x1f308; 4 图示&#x1f3f3;️‍&#x1f308; 5 可视化项目源码…

C++学习/复习20--继承的权限/向上转换/重定义/默认成员函数/友元/静态成员/菱形虚拟继承/组合

一、继承的概念 二、继承的权限 三、向上转换 四、重定义(隐藏) 五、派生类的默认成员函数 六、继承与友元 七、继承与静态成员 八、菱形继承 数据冗余与二义性 虚拟继承(virtual) 九、继承组合

从零开始精通Onvif之常见故障排查

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 概述 Onvif作为统一标准&#xff0c;在理论上应该能够解决网络视频监控产品之间的兼容性问题。但在实际使用中&#xff0c;仍然会出现各种各样的…