Ch07 Dijkstra算法

7/25/2019 Algorithm

# Dijkstra算法

求图中两个节点之间最短路径问题:贪婪思想,路径必须是正数,如果是负数用Bellman-Ford算法

image-20230420232705737
  1. 求最短路径
  2. 底层使用广度优先算法
  3. 有三个集合要用:
  • 记录被访问过的顶点
  • 记录该顶点到起始点的最短路径
  • 记录该路径的前驱结点

图解: https://www.bilibili.com/video/BV1zz4y1m7Nq/?share_source=copy_web&share_times=1&vd_source=1a7c0e12ae4c11965d82c6b8edcbdf0f

image-20230420234332876

核心思想:选取最近节点,广度优先更新周围节点,再选取最近节点,以此类推

import java.util.Arrays;

public class DijkstraDemo {

	public static void main(String[] args) {
		char[] vertex = new char[] {'A','B','C','D','E','F','G'};
		int[][] matrix = new int[vertex.length][vertex.length];
		final int N = 65535;
		matrix[0] = new int[]{N,5,7,N,N,N,2};
		matrix[1] = new int[]{5,N,N,9,N,N,3};
		matrix[2] = new int[]{7,N,N,N,8,N,N};
		matrix[3] = new int[]{N,9,N,N,N,4,N};
		matrix[4] = new int[]{N,N,8,N,N,5,4};
		matrix[5] = new int[]{N,N,N,4,5,N,6};
		matrix[6] = new int[]{2,3,N,N,4,6,N};
		Graph graph = new Graph(vertex, matrix);
		graph.dijkstra(6);
		

	}

}

class Graph{
	public char[] vertex;
	public int[][] matrix;
	public VisitedVertex vv;
	public Graph(char[] vertex, int[][] matrix) {
		super();
		this.vertex = vertex;
		this.matrix = matrix;
	}
	public void showGraph() {
		for(int i = 0; i < vertex.length; i++) {
			for(int j = 0; j < vertex.length; j++) {
				System.out.printf("%10d", matrix[i][j]);
			}
			System.out.println();
		}
	}
	//算法,先更新开始节点
	public void dijkstra(int index) {
		vv = new VisitedVertex(vertex.length, index);
		update(index);
		for(int i = 0; i < vertex.length;i++) {
			index = vv.nextVertex();
			update(index);
		}
		
		//输出
		System.out.println("distance");
		for(int i : vv.distance) {
			System.out.print(i + "  ");
		}
		System.out.println("pre");
		for(int i : vv.pre) {
			System.out.print(i + "  ");
		}
	}
	//访问某个点之后的更新
	public void update(int index) {
		int len = 0;
		//广度遍历
		for(int i = 0; i < matrix[index].length;i++) {
			//距离增加
			len = matrix[index][i] + vv.distance[index];
			//更新距离,前驱结点
			if(vv.isVisited[i] == 0 && len < vv.distance[i]) {
				vv.distance[i] = len;
				vv.pre[i] = index;
			}
		}
		
	}
	
}
//已访问过的顶点的信息
class VisitedVertex{
	//记录顶点是否被访问过
	public int isVisited[];
	//值为该节点的前驱结点,会动态更新
	public int pre[];
	//值为出发顶点到其他所有顶点的距离
	public int distance[];
	//构造
	public VisitedVertex(int length, int index) {
		isVisited = new int[length];
		isVisited[index] = 1;
		pre = new int[length];
		Arrays.fill(pre, -1);
		distance = new int[length];
		Arrays.fill(distance, 65535);
		distance[index] = 0;
	}
	//下一个要访问的节点
	public int nextVertex() {
		int min = 65536;
		int index = 0;
		for(int i = 0; i < isVisited.length; i++) {
			if(isVisited[i] == 0 && distance[i] < min) {
				min = distance[i];
				index = i;
			}
		}
		isVisited[index] = 1;
		return index;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
Last Updated: 11/19/2024, 1:54:38 PM