Dijkstra
事前準備
visted[]
記錄「出發頂點」與下一次「距離最短的頂點」,「是否已訪問」的陣列。distance[]
記錄從「出發頂點」到每個頂點的最短距離。preVertex[]
記錄「前一個頂點」是誰,預設為全0。- MAX常數,代表無法連結,在這裡用10000。
- matrix表格,記錄某個頂點到某個頂點的距離。
出發頂點
出發頂點為0
visted陣列,把出發頂點0設為True,預設全為False。
頂點 | 0 | 1 | 2 | 3 |
visted | T | F | F | F |
把「出發頂點」到「出發頂點」的距離設為0,自己連自己沒有距離,其它頂點都用MAX。
頂點 | 0 | 1 | 2 | 3 |
distance | 0 | MAX | MAX | MAX |
出發頂點0的相鄰頂點
出發頂點的相鄰頂點為1與2,記錄「出發頂點」→「相鄰頂點」的距離。
出發頂點0到相鄰頂點1
出發頂點0 → 相鄰頂點1的距離為1,更新距離表。
更新頂點1的前一個頂點為0,更新preVertex。
頂點 | 0 | 1 | 2 | 3 |
distance | 0 | 1 | MAX | MAX |
preVertex | 0 |
出發頂點0到相鄰頂點2
出發頂點0 → 相鄰頂點2的距離為10。
更新頂點2的前一個頂點為0,更新preVertex。
distance | 0 | 1 | 2 | 3 |
distance | 0 | 1 | 10 | MAX |
preVertex | 0 | 0 |
距離最短的頂點1
在distance陣列中,找到最短距離的頂點,且沒有被訪問過。
從以下表格中,找到的是1這個頂點,它與出發頂點的距離為1,為最短距離的頂點,把它設為已訪問。
頂點 | 0 | 1 | 2 | 3 |
distance | 0 | 1 | 10 | MAX |
visted | T | F | F |
相鄰頂點2與3
距離最短的頂點1的相鄰頂點為0、2、3,但0已經被訪問過了visted[0] = T
,所以沒被訪問過的相鄰頂點為2與3。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | F | F |
distance | 0 | 1 | 10 | MAX |
0→1→2的距離
先得到「出發頂點0」到「最短距離頂點1」的距離,到distance表格查,distance記錄出發頂點0到各個頂點的最短距離。
頂點 | 0 | 1 | 2 | 3 |
distance | 0 | 1 | 10 | MAX |
根據上面的表格得到頂點1與出發頂點的最短距離是1。
0 → 1 = 1
頂點1到頂點2的距離,則到matrix表格查,matrix[1][2] = 2
。
1 → 2 = 2
將上面的距離加總,結果如下。
0 → 1 → 2 = 1 + 2 = 3
原本的距離表出發頂點0到頂點2為10,3比10小,把距離表更新。
更新頂點2的前一個頂點為1,因為從0→2跟0→1→2,0→1→2距離更短,前一個頂點是1,更新preVertex。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | F | F |
distance | 0 | 1 | MAX | |
preVertex | 0 |
0→1→3的距離
先得到「出發頂點0」到「最短距離頂點1」的距離,到distance表格查,distance記錄出發頂點0到各個頂點的最短距離。
頂點 | 0 | 1 | 2 | 3 |
distance | 0 | 1 | 10 | MAX |
0 → 1 = 1
頂點1到頂點3的距離,則到matrix表格查,matrix[1][3] = 8
。
1 → 3 = 8
將上面的距離加總,結果如下。
0 → 1 → 3 = 1 + 8 = 9
原本的距離表出發頂點0到頂點3為MAX,9比MAX小,把距離表更新。
更新頂點3的前一個頂點為1,因為從0→3跟0→1→3,0→1→3距離更短,前一個頂點是1,更新preVertex。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | F | F |
distance | 0 | 1 | 3 | |
preVertex | 0 | 1 | 1 |
距離最短的頂點2
在distance陣列中,找到最短距離的頂點,且沒有被訪問過。
從以下表格中,找到的是2這個頂點,距離為3,把它設為已訪問。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | F | |
distance | 0 | 1 | 3 | 9 |
preVertex | 0 | 1 | 1 |
相鄰頂點3
頂點2的相鄰頂點為0、1、3,但0、1已經被訪問過了,所以沒被訪問過的相鄰頂點為3。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | T | F |
distance | 0 | 1 | 3 | 9 |
根據上面的表格distance,出發頂點0到頂點2的最短路徑得到3。
0 → 2 = 3
頂點2到頂點3的距離,則到matrix表格查,matrix[2][3] = 3
。
2 → 3 = 3
將上面的距離加總,結果如下。
0 → 2 → 3 = 3 + 3 = 6
原本的距離表出發頂點0到頂點3為9,6比9小,距離表更新。
更新頂點3的前一個頂點為2,因為0→1→3 = 9,而0→2→3 = 6,前一個頂點為2的路徑更短,更新preVertex。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | T | F |
distance | 0 | 1 | 3 | |
preVertex | 0 | 1 |
距離最短的頂點3
在distance陣列中,找到最短距離的頂點,且沒有被訪問過的為頂點3,設為已訪問。
頂點 | 0 | 1 | 2 | 3 |
visted | T | T | T | |
distance | 0 | 1 | 3 | 6 |
preVertex | 0 | 1 | 2 |
因為其它頂點全部都訪問過了,求出頂點0到各個頂點最短距離如下:
頂點 | 0 | 1 | 2 | 3 |
distance | 0 | 1 | 3 | 6 |
假設要尋找頂點0→頂點2的最短路徑,參考下表,頂點2的前一個頂點1,1→2,1的前一個頂點是0,0→1→2。
頂點 | 0 | 1 | 2 | 3 |
preVertex | 0 | 1 | 2 |
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
public class Dijkstra {
private int[][] matrix ;
private boolean[] visted;
private int[] preVertex;
private int[] distance;
private int vertexLen = 4;
public static final int MAX = 10000;
public Dijkstra() {
matrix = new int[vertexLen][vertexLen];
matrix[0] = new int[]{MAX, 1, 10, MAX};
matrix[1] = new int[]{1, MAX, 2, 8};
matrix[2] = new int[]{10, 2, MAX, 3};
matrix[3] = new int[]{MAX, 8, 3, MAX};
visted = new boolean[vertexLen];
preVertex = new int[vertexLen];
distance = new int[vertexLen];
Arrays.fill(distance, MAX);
}
public void setStart(int startIndex) {
distance[startIndex] = 0;
visted[startIndex] = true;
}
public void dijkstra(int index) {
int len = 0;
for (int i = 0; i < matrix[index].length; i++) {
len = distance[index] + matrix[index][i];
if (!visted[i] && len < distance[i]) {
distance[i] = len;
preVertex[i] = index;
}
}
}
public static void main(String[] args) {
Dijkstra dijkstra = new Dijkstra();
dijkstra.setStart(0);
dijkstra.dijkstra(0);
System.out.println(Arrays.toString(dijkstra.distance));
for (int i = 0; i < dijkstra.vertexLen - 1; i++) {
int vertex = dijkstra.findMinPathVertex();
System.out.println("vertex = " + vertex);
dijkstra.dijkstra(vertex);
System.out.println(Arrays.toString(dijkstra.distance));
System.out.println(Arrays.toString(dijkstra.preVertex));
System.out.println("============");
}
}
public int findMinPathVertex() {
int min = MAX;
int vertex = 0;
for (int i = 0; i < vertexLen; i++) {
if (!visted[i] && distance[i] < min) {
min = distance[i];
vertex = i;
}
}
visted[vertex] = true;
return vertex;
}
}