数据结构重读——单源最短路径(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

相关文章

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,或者在别人的电脑上,想

Python中Windows和macOS文件路径格式不一致的解决方法

《Python中Windows和macOS文件路径格式不一致的解决方法》在Python中,Windows和macOS的文件路径字符串格式不一致主要体现在路径分隔符上,这种差异可能导致跨平台代码在处理文... 目录方法 1:使用 os.path 模块方法 2:使用 pathlib 模块(推荐)方法 3:统一使

一文教你解决Python不支持中文路径的问题

《一文教你解决Python不支持中文路径的问题》Python是一种广泛使用的高级编程语言,然而在处理包含中文字符的文件路径时,Python有时会表现出一些不友好的行为,下面小编就来为大家介绍一下具体的... 目录问题背景解决方案1. 设置正确的文件编码2. 使用pathlib模块3. 转换路径为Unicod

MySQL9.0默认路径安装下重置root密码

《MySQL9.0默认路径安装下重置root密码》本文主要介绍了MySQL9.0默认路径安装下重置root密码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录问题描述环境描述解决方法正常模式下修改密码报错原因问题描述mysqlChina编程采用默认安装路径,

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

python获取当前文件和目录路径的方法详解

《python获取当前文件和目录路径的方法详解》:本文主要介绍Python中获取当前文件路径和目录的方法,包括使用__file__关键字、os.path.abspath、os.path.realp... 目录1、获取当前文件路径2、获取当前文件所在目录3、os.path.abspath和os.path.re

hdu2544(单源最短路径)

模板题: //题意:求1到n的最短路径,模板题#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#i

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig