单源最短路径问题(Java)
单源最短路径问题(Java)
文章目录
- 单源最短路径问题(Java)
- 1、问题描述
- 2、算法思路
- 3、代码实现
- 4、算法正确性和计算复杂性
- 4.1 贪心选择性质
- 4.2 最优子结构性质
- 4.3 计算复杂性
- 5、参考资料
1、问题描述
给定带权有向图
G=(V,E),其中每条边的权是非负实数
。另外,还给定V中的一个顶点, 称为源
。现在要计算从源到所有其他各顶点的最短路长度
。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题
。
其中,V表示顶点集合,E表示各个节点之间的边。
2、算法思路
对于单源最短路径问题,Dijkstra算法
是解决这个问题的贪心
算法。
基本思想
设置顶点集合S
并不断地做贪心
选择来扩充
这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S 中仅含有源。设u是G 的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u 的特殊路径
,并用数组dist
记录当前每个顶点所对应的最短特殊路径长度
。
Dijkstra 算法每次从v-s中取出具有最短特殊路长度的顶点u
,将u添加到S中,同时对数组dist 进行必要的修改。一旦S包含了所有V中顶点,dist数组就记录了从源到所有其他顶点之间的最短路径长度。
Dijkstra 算法可描述如下。
其中, 输入的带权有向图是G = (V, E) , V = {1 , 2, …, n} 。顶点v是源。a是一个二维数组,a[i][j]表示边(i,j)的权。当(i, j) 时,a[i][j]是一个大数。如dist[i]表示当前从源到顶点t的最短特殊路径长度。
3、代码实现
例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下页的表中。
题目示意图
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;/*** TODO 1 --> 4 --> 3 --> 5*/
public class Solution {private static int vNum, eNum;private static int[] v;private static float[][] e;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.print("input the number of vertix and edge:");vNum = scanner.nextInt();eNum = scanner.nextInt();v = new int[vNum];e = new float[vNum + 1][vNum + 1];for (int i = 0; i < e.length; i++) {for (int j = 0; j < e.length; j++) {e[i][j] = Float.MAX_VALUE;}}System.out.print("input the vertix information:");for (int i = 0; i < v.length; i++) {v[i] = scanner.nextInt();}System.out.println("input the weight of edges:");for (int i = 0; i < eNum; i++) {int start = scanner.nextInt(), target = scanner.nextInt();e[start][target] = (float) scanner.nextInt();}System.out.print("顶点有:");for (int i = 0; i < v.length; i++) {if (i == v.length - 1) {System.out.println(v[i]);} else {System.out.print(v[i] + ", ");}}System.out.println("边与边之间的距离:");for (int i = 1; i < e.length; i++) {for (int j = 1; j < e.length; j++) {if (i != j && e[i][j] != Float.MAX_VALUE) {System.out.print("[" + i + ", " + j + "] = " + e[i][j] + "; ");}}}System.out.println();int[] path = new int[vNum + 1];float[] dist = new float[vNum + 1];Dijkstra(v[0], e, dist, path);System.out.print("Dijkstra路径为:");List<Integer> list = new ArrayList<>();list.add(vNum);list.add(path[vNum]);while (true) {if (path[list.get(list.size() - 1)] == 1) {list.add(1);break;}list.add(path[list.get(list.size() - 1)]);}for (int j = list.size() - 1; j >= 0; j--) {if (j != 0) {System.out.print(list.get(j) + "-->");} else {System.out.println(list.get(j));}}System.out.println("从顶点1到各顶点最短距离:");for (int i = 1; i < dist.length; i++) {System.out.println("dist[" + i + "] = " + dist[i]);}}public static void Dijkstra(int vertix, float[][] weight, float[] dist, int[] path) {int n = dist.length - 1;if (vertix < 1 || vertix > n + 1) {return;}boolean[] vis = new boolean[n + 2];// initializefor (int i = 1; i <= n; i++) {dist[i] = weight[vertix][i];vis[i] = false;if (dist[i] == Float.MAX_VALUE) {path[i] = 0;} else {path[i] = vertix;}}dist[vertix] = 0;vis[vertix] = true;for (int i = 1; i < n; i++) {float tmp = Float.MAX_VALUE;int u = vertix;for (int j = 1; j <= n; j++) {if ((!vis[j]) && (dist[j] < tmp)) {u = j;tmp = dist[j];}}vis[u] = true;for (int j = 1; j <= n; j++) {if ((!vis[j]) && (weight[u][j] < Float.MAX_VALUE)) {float newDist = dist[u] + weight[u][j];if (newDist < dist[j]) {dist[j] = newDist;path[j] = u;}}}}}
}
运行结果
Dijkstra算法的迭代过程:
图解过程
4、算法正确性和计算复杂性
4.1 贪心选择性质
(1)根据算法可知,最短距离是最小的路长,故
dist[x]<= d(v,x)
(2)假设存在另外一条更短路红色线所示,故
d(v,x)+d(x,u)=d(v,u)<dist[u]
(3)由(1)(2)可知,dist[x]<dist[u]。此为矛盾,因为如果(3)成立,此时应该选择 x进入S集合,即选择具有最短特殊路径的顶点是x,而不是u。(因为根据最短路径算法,总是选取最短路径的顶点进入S)
4.2 最优子结构性质
该性质描述为:如果S(i,j)={Vi…Vk…Vs…Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么S(k,s)必定是从k到s的最短路径。下面证明该性质的正确性。
假设S(i,j)={Vi…Vk…Vs…Vj}是从顶点i到j的最短路径,则有S(i,j)=S(i,k)+S(k,s)+S(s,j)。而S(k,s)不是从k到s的最短距离,那么必定存在另一条从k到s的最短路径S’(k,s),那么S’(i,j)=S(i,k)+S’(k,s)+S(s,j)<S(i,j)。则与S(i,j)是从i到j的最短路径相矛盾。因此该性质得证。
4.3 计算复杂性
对于具有n个顶点和e条边的带权有向图, 如果用带权邻接矩阵表示这个图,那么Dijkstra算法的主循环体需要O(n) 时间。这个循环需要执行n-1次,所以完成循环需要
0(n2)时间。算法的其余部分所需要时间不超过0(n2)。
5、参考资料
- 算法设计与分析(第四版)
单源最短路径问题(Java)相关推荐
- Dijkstra 单源最短路径算法 Java实现
Dijkstra 单源最短路径算法 Java实现 算法导入 算法核心 复杂度分析 时间复杂度 空间复杂度 代码实现 参考资料 结尾 算法导入 在图论中,求最短路径有一个经典的算法 Dijkstra算法 ...
- java有向图最短路径_单源最短路径之Java实现(使用Java内置优先队列)
import java.util.*; /** * 用堆实现了从一个点到其他点的最短路径 * @author 李赫元 */ public class ShortestPath { /**有n个节点*/ ...
- 用java单源最短路径问题_单源最短路径-贪心算法
单源最短路径,关于这个问题的贪心算有点不好理解,分析后续补充,代码也需要后续优化,便于理解 package test; import java.util.ArrayList; import java. ...
- 用java编写的一个迪杰斯特拉算法(单源最短路径算法,Dijkstra算法)。
可以用于有向图和无向图.用负数表示该有向路不通.在EditPlus上写的,所以就一个.java文件. package Test;import java.util.TreeMap; import jav ...
- 用java单源最短路径问题_java 单源最短路径问题
import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util ...
- p3371 单源最短路径(弱化版)-java题解-最短路
弱化版传送门: P3371 [模板]单源最短路径(弱化版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目背景 本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通 ...
- p4779 单源最短路径(标准版)-java版
传送门: P4779 [模板]单源最短路径(标准版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P4779 先给 ...
- 单源最短路径问题——分支限界法(Java)
1. 前置芝士 1.1 分支限界法求解目标 分支限界法与回溯法的不同求解目标: 回溯法的求解目标:找出解空间树中满足约束条件的所有解: 分支限界法的求解目标:找出满足约束条件的一个解,或是在满足约束条 ...
- 分支限界法 java_算法java实现–分支限界法–单源最短路径问题 | 学步园
单源最短路径问题的java实现(分支限界法) 具体问题描述以及C/C++实现参见网址 http://blog.csdn.net/liufeng_king/article/details/8900872 ...
最新文章
- Android Activity 和 ViewGroup中事件触发和传递机制
- 这款Linux发行版已经适配200+移动设备
- 某互联网企业技术发展史(四)配置nginx和mysql兼容Yii框架,上传网站并调试成功...
- SAP S/4HANA客户关系管理之变
- 深入理解重要的编程模型
- LOJ:相框(欧拉回路、分类讨论)
- 第五十期:工作强度超996,失业半年即出局,硅谷为何如此“嗜血”?
- MaxCompute 存储设计
- Python命令行参数
- android 右边抽屉,android – 抽屉在右侧抽屉中切换
- 中对缺失数据的预处理_数据预处理也有套路的
- 运维技术之二(2)、docker安装jumpserver
- Rviz教程系列第一章之Markers
- 小战Java笔记_SE_Identifier(标识符)
- Android、Java超详细的身份证验证工具
- 三星s8android9,三星S8官方国行版安卓9固件rom刷机包:CHC-G9500ZCS3DSD5
- C语言入门-绝对值(abs)
- 服务器设置防火墙网站打不开,部分网站打不开如何处理?
- aix 到 linux的网络,通过VIOS实现AIX系统的网络虚拟化
- left.php源代码分析