单源最短路径问题(Java)
创始人
2024-02-21 07:21:53
0

单源最短路径问题(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 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)

(3)由(1)(2)可知,dist[x] 在这里插入图片描述

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)

4.3 计算复杂性

对于具有n个顶点和e条边的带权有向图, 如果用带权邻接矩阵表示这个图,那么Dijkstra算法的主循环体需要O(n) 时间。这个循环需要执行n-1次,所以完成循环需要
0(n2)时间。算法的其余部分所需要时间不超过0(n2)。

5、参考资料

  • 算法设计与分析(第四版)

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...