数据结构重读——单源最短路径(Dijkstra) 转自酷勤

2023-11-03 23:51

本文主要是介绍数据结构重读——单源最短路径(Dijkstra) 转自酷勤,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

单源最短路径:给定带权有向图和源点v,求从v到G中其余各点的最短路径。

Dijkstra算法非常类似于最小生成树算法(的Prim)。

算法

0、假设源为v0,设置辅助变量dist和pre,优先队列pq,按照dist[x]从小到达排序(小顶堆)。

1、如果v0->i连通,初始化dist[i]为w[v0][i]。放(dist[i], i)入pq。

2、循环,直到pq为空。

2.1、取出pq中最小的,设其下标为x,

2.2、遍历图matrix[x][i], i 0->nvexs。如果dist[x]+matrix[x][i] < dist[i],更新dist[i]=dist[x]+matrix[x][i],并且放(dist[i], i)入pq,并且pre[i] = x。

3、如果dist[i]<INFINTE,输出dist[i],并倒序输出pre[?]直到为-1。

上述这么搞,时间复杂度应该为O(nlogn)

好了,代码如下:

图及输入

 

 

01 import java.util.Arrays;

02 import  java.util.Scanner;

03  

04 public class Graph {

05  

06 public Graph() {

07 scan = new Scanner(System.in);

08 }

09  

10 public void input() {

11 intput_vexs();

12 input_arcs();

13 }

14  

15 private  void intput_vexs() {

16 // Input vexs

17 int nvexs = 0;

18 System.out.println("Please enter n for vexs:");

19 if (scan.hasNextInt()) {

20 nvexs = scan.nextInt();

21 }

22 vexs = new int[nvexs];

23 for  (int i = 0; i < nvexs; i++) {

24 System.out.println("Please enter a integer for vex(" + i + "):");

25 if (scan.hasNextInt()) {

26 vexs[i] = scan.nextInt();

27 }

28 }

29 }

30  

31 private void input_arcs() {

32 // Input weight between vexs

33 int nvexs = vexs.length;

34 matrix = new  int[nvexs][];

35 for (int i = 0; i < nvexs; i++) {

36 matrix[i] = new int[nvexs];

37 Arrays.fill(matrix[i], Integer.MAX_VALUE);

38 }

39 int narcs = 0;

40 int x = 0, y = 0, w = 0;

41 System.out.println("Please enter n for arcs:");

42 if (scan.hasNextInt()) {

43 narcs = scan.nextInt();

44 }

45 for  (int i = 0; i < narcs; i++) {

46 System.out.println("Please enter x, y, w for arc(" + i + "):");

47 if (scan.hasNextInt()) {

48 x = scan.nextInt();

49 x = vex2i(x);

50 }

51 if (scan.hasNextInt()) {

52 y = scan.nextInt();

53 y = vex2i(y);

54 }

55 if (scan.hasNextInt()) {

56 w = scan.nextInt();

57 }

58 if (x == -1 || y == -1 || w <= 0) {

59 System.out.println("x or y or w invalid, please enter again:");

60 i--;

61 } else  {

62 matrix[x][y] = w;

63 }

64 }

65 }

66  

67 public  int vex2i(int v) {

68 for (int i = 0; i < vexs.length; i++) {

69 if (v == vexs[i]) {

70 return i;

71 }

72 }

73 return -1;

74 }

75  

76 public  int[][] matrix = null;

77 public int[] vexs = null;

78 private Scanner scan = null;

79  

80 public static void main(String[] args) {

81 Graph g = new  Graph();

82 g.input();

83 System.out.println("vexs:");

84 for (int  i = 0; i < g.vexs.length; i++) {

85 System.out.print(g.vexs[i] + " ");

86 }

87 System.out.println();

88 System.out.println("matrix:");

89 for (int i = 0; i < g.matrix.length; i++) {

90 for (int j = 0; j < g.matrix[i].length; j++) {

91 System.out.format("%11d ", g.matrix[i][j]);

92 }

93 System.out.println();

94 }

95 }

96 }

 

 

Dijkstra算法

 

 

01 import java.util.Comparator;

02 import java.util.PriorityQueue;

03  

04 class DijPair {

05  

06 public DijPair(int i, int w) {

07 this.i = i;

08 this.w = w;

09 }

10  

11 public int i;

12 public  int w;

13 }

14  

15 public class Dijkstra {

16  

17 public void SetGraph(Graph g) {

18 this.g = g;

19 }

20  

21 public void ShortPath(int start) {

22 // Convert start to position

23 int v = g.vex2i(start);

24 if (v == -1) {

25 System.out.println("start vex "  + start + " invalid");

26 }

27 // PriorityQueue

28 PriorityQueue<DijPair> pq = new PriorityQueue<DijPair>(10,

29 new Comparator<DijPair>() {

30 @Override

31 public int compare(DijPair a, DijPair b) {

32 return  a.w - b.w;

33 }

34 });

35 // Init dist & pre

36 int dist[] = new  int[g.vexs.length];

37 int  pre[] = new int[g.vexs.length];

38 for (int i = 0; i < g.matrix[v].length; i++) {

39 pre[i] = -1;

40 dist[i] = g.matrix[v][i];

41 if (dist[i] != Integer.MAX_VALUE) {

42 pre[i] = v;

43 pq.add(new DijPair(i, dist[i]));

44 }

45 }

46 // While not empty

47 while (!pq.isEmpty()) {

48 // Pool the smallest w and it's i

49 DijPair cur = pq.poll();

50 if (cur == null) {

51 break;

52 }

53 // Update dist if smaller

54 for (int i = 0; i < g.matrix[cur.i].length; i++) {

55 if (g.matrix[cur.i][i] != Integer.MAX_VALUE

56 && dist[cur.i] + g.matrix[cur.i][i] < dist[i]) {

57 dist[i] = dist[cur.i] + g.matrix[cur.i][i];

58 pre[i] = cur.i;

59 pq.add(new DijPair(i, dist[i]));

60 }

61 }

62 }

63 // End

64 for (int i = 0; i < dist.length; i++) {

65 if (dist[i] != Integer.MAX_VALUE) {

66 System.out.format("short_dist %d to %d is %d ", start,

67 g.vexs[i], dist[i]);

68 System.out.print(", path is ");

69 System.out.format("%d ", g.vexs[i]);

70 int tmp = pre[i];

71 while (tmp != -1) {

72 System.out.format("<- %d ", g.vexs[tmp]);

73 tmp = pre[tmp];

74 }

75 System.out.println();

76 }

77 }

78 }

79  

80 private Graph g = null;;

81  

82 public  static void main(String[] args) {

83 Graph g = new Graph();

84 g.input();

85 Dijkstra dij = new Dijkstra();

86 dij.SetGraph(g);

87 dij.ShortPath(0);

88 }

89 }

 

 

测试图:

测试数据:

 

 

01 6

02 0

03 1

04 2

05 3

06 4

07 5

08 8

09 0 5 100

10 0 2 10

11 0 4 30

12 1 2 5

13 2 3 50

14 4 3 20

15 3 5 10

16 4 5 60

 

 

测试输出:

 

 

1 short_dist 0 to 2 is 10 , path is 2 <- 0

2 short_dist 0 to 3 is 50 , path is 3 <- 4 <- 0

3 short_dist 0 to 4 is 30 , path is 4 <- 0

4 short_dist 0 to 5 is 60 , path is 5 <- 3 <- 4 <- 0

这篇关于数据结构重读——单源最短路径(Dijkstra) 转自酷勤的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/341741

相关文章

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

VSCode设置python SDK路径的实现步骤

《VSCode设置pythonSDK路径的实现步骤》本文主要介绍了VSCode设置pythonSDK路径的实现步骤,包括命令面板切换、settings.json配置、环境变量及虚拟环境处理,具有一定... 目录一、通过命令面板快速切换(推荐方法)二、通过 settings.json 配置(项目级/全局)三、

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键

如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)

《如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)》:本文主要介绍如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)问题,具有很好的参考价值,希望对大家有所帮助,如有... 目录先在你打算存放的地方建四个文件夹更改这四个路径就可以修改默认虚拟内存分页js文件的位置接下来从高级-

一文详解如何查看本地MySQL的安装路径

《一文详解如何查看本地MySQL的安装路径》本地安装MySQL对于初学者或者开发人员来说是一项基础技能,但在安装过程中可能会遇到各种问题,:本文主要介绍如何查看本地MySQL安装路径的相关资料,需... 目录1. 如何查看本地mysql的安装路径1.1. 方法1:通过查询本地服务1.2. 方法2:通过MyS

Python如何调用指定路径的模块

《Python如何调用指定路径的模块》要在Python中调用指定路径的模块,可以使用sys.path.append,importlib.util.spec_from_file_location和exe... 目录一、sys.path.append() 方法1. 方法简介2. 使用示例3. 注意事项二、imp

使用Python实现矢量路径的压缩、解压与可视化

《使用Python实现矢量路径的压缩、解压与可视化》在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要,本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,... 目录引言核心功能概述1. 路径命令解析2. 路径数据压缩3. 路径数据解压4. 可视化代码实现详解1

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

Windows系统下如何查找JDK的安装路径

《Windows系统下如何查找JDK的安装路径》:本文主要介绍Windows系统下如何查找JDK的安装路径,文中介绍了三种方法,分别是通过命令行检查、使用verbose选项查找jre目录、以及查看... 目录一、确认是否安装了JDK二、查找路径三、另外一种方式如果很久之前安装了JDK,或者在别人的电脑上,想