数据结构重读——单源最短路径(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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值