最短路徑(Dijstra and Floyd)
數據結構:鄰接表
private final int maxValue = Integer.MAX_VALUE;
private int[][] matrix;
public Graph(int v) {
matrix = new int[v][v];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] = maxValue;
}
}
}
void addEdge(int s, int t, int w) {
matrix[s][t] = w;
}
Dijstra
圖解就不寫了,直接引用他人寫好的,圖解鏈接
測試數據 7 9 0 1 6 0 3 2 1 2 5 1 5 3 3 1 7 3 4 5 4 6 1 4 5 5 5 2 3
對應結果
/**
* 測試數據 7 9 0 1 6 0 3 2 1 2 5 1 5 3 3 1 7 3 4 5 4 6 1 4 5 5 5 2 3
*
* @param g 鄰接矩陣
* @param s 起點
*/
void dijstra(int[][] g, int s) {
// 最短路徑長度
int[] shortest = new int[matrix.length];
// 判斷最短路徑是否已經求出
int[] visited = new int[matrix.length];
// 初始化源節點
shortest[s] = 0;
visited[s] = 1;
int count = visited.length - 1;
// 每次循環都計算出到一個節點的最短路徑,所以一共循環 n-1 次
while (count-- > 0) {
int min = Integer.MAX_VALUE;
int index = -1;
// 找出到未計算區域中距離已經計算區域最近的點,保存在index中
for (int j = 0; j < matrix.length; j++) {
// 已經求出最短路徑的節點不需要再加入計算並判斷加入節點後是否存在更短路徑
if (visited[j] == 0 && matrix[s][j] < min) {
min = matrix[s][j];
index = j;
}
}
// 更新最短路徑
shortest[index] = min;
visited[index] = 1;
// 更新從index節點到其他節點的較短路徑
for (int j = 0; j < matrix.length; j++) {
// 這裏不要使用加法,改成減法,否則Integer.MAX_VALUE相加會溢出成負數
if (visited[j] == 0
&& matrix[s][index] < matrix[s][j] - matrix[index][j]) {
matrix[s][j] = matrix[s][index] + matrix[index][j];
}
}
}
// 打印結果
System.out.println("|------|----------|---------|");
System.out.printf("|------source node:%3s------|\n", s);
System.out.println("| node | shortest | visited |");
System.out.println("|------|----------|---------|");
for (int i = 0; i < shortest.length; i++) {
System.out.printf("|%6s|%10s|%9s|\n", i, shortest[i],
visited[i] == 1);
}
System.out.println("|------|----------|---------|");
}
}
Floyd
核心:嘗試將每個點作爲中轉站,看是否能夠使得原本的距離變短
測試數據 7 9 0 1 6 0 3 2 1 2 5 1 5 3 3 1 7 3 4 5 4 6 1 4 5 5 5 2 3
void floyd(int[][] g) {
/**
* 使用減法避免溢出成負數(權值沒有負數)
* 記憶的時候還是記憶成 i->j (g[i][j]) 通過 k 中轉是否可以減少距離 (裏面2層通過最外面一層的進行中轉)
* 即 g[i][j] > g[i][k] + g[k][j]
*/
for (int k = 0; k < g.length; k++)
for (int i = 0; i < g.length; i++)
for (int j = 0; j < g.length; j++)
if (g[i][j] - g[i][k] > g[k][j])
g[i][j] = g[i][k] + g[k][j];
// 輸出結果
for (int i = 0; i < g.length; i++) {
for (int j = 0; j < g.length; j++) {
if (g[i][j] == maxValue) {
System.out.printf("%3s ", "∞");
} else {
System.out.printf("%3s ", g[i][j]);
}
}
System.out.println();
}
}