目錄
1.迪傑斯特拉(Dijkstra)算法介紹
迪傑斯特拉(Dijkstra)算法是典型最短路徑算法,用於計算-一個節點到其他節點的最
短路徑。它的主要特點是以起始點爲中心向外層層擴展(廣^度優先搜索思想),直到
擴展到終點爲止。
2.克魯斯卡爾最佳實踐公交站問題
1)戰爭時期,勝利鄉有7個村莊(A,B,C,D,E,F,G),現在有六個郵差,從G點出發,需要分別把郵件分別送到A,B,C,D,E,F六個村莊
2)各個村莊的距離用邊線表示(權),比如A-B距離5公里
3) 問:如何計算出G村莊到其它各個村莊的最短距離?
4)如果從其它點出 發到各個點的最短距離又是多少?
3.迪傑斯特拉(Dijkstra)算法過程
設置出發頂點爲v,頂點集金V{v1,2v.,..},v到V中各頂點的距離構成距離集合Dis,Dis{d1,2,d...},. Dis集 合記錄着v到圖中各頂點的距離(到自身可以看作0,v到vi距離對應爲di)
1)從Dis中選擇值最小的di並移出Dis集合,同時移出V集合中對應的頂點vi,此時的v到vi即爲最短路徑
2)更新Dis集合, 更新規則爲:比較v到V集合中項點的距離值, 與v通過vi到V集合中頂點的距離值,保留值較小的一個(同時也應該更新頂點的前驅節點爲vi,表明是通過vi到達的)
3) 重複執行兩步驟,直到最短路徑項點爲目標頂點即可結束
4.代碼實現
package com.example.datastructureandalgorithm.dijkstra;
import java.util.Arrays;
/**
* 迪傑斯特拉算法
*
* @author 浪子傑
* @version 1.0
* @date 2020/6/27
*/
public class DijkstraDemo {
public static void main(String[] args) {
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int[][] matrix = new int[vertex.length][vertex.length];
final int N = 65535;
matrix[0] = new int[]{0, 5, 7, N, N, N, 2};
matrix[1] = new int[]{5, 0, N, 9, N, N, 3};
matrix[2] = new int[]{7, N, 0, N, 8, N, N};
matrix[3] = new int[]{N, 9, N, 0, N, 4, N};
matrix[4] = new int[]{N, N, 8, N, 0, 5, 4};
matrix[5] = new int[]{N, N, N, 4, 5, 0, 6};
matrix[6] = new int[]{2, 3, N, N, 4, 6, 0};
Graph graph = new Graph(vertex, matrix);
graph.show();
graph.dsj(6);
graph.showDjs();
}
}
class Graph {
/**
* 存放頂點的數組
*/
private char[] vertex;
/**
* 鄰接矩陣
*/
private int[][] matrix;
/**
* 已訪問頂點集合
*/
private VisitedVertex visitedVertex;
public Graph(char[] vertex, int[][] matrix) {
this.vertex = vertex;
this.matrix = matrix;
}
public void show() {
for (int[] ints : matrix) {
System.out.println(Arrays.toString(ints));
}
}
public void dsj(int index) {
visitedVertex = new VisitedVertex(vertex.length, index);
update(index);
for (int i = 1; i < vertex.length; i++) {
// 找到新的訪問節點
index = visitedVertex.updateArr();
// 繼續更新
update(index);
}
}
/**
* 更新index節點到周圍節點的距離和前驅節點
*
* @param index
*/
public void update(int index) {
// 循環鄰接矩陣
for (int i = 0; i < matrix[index].length; i++) {
// 到第i個節點的距離爲,出發頂點到index距離+index到i節點的距離
int length = visitedVertex.getDis(index) + matrix[index][i];
// 和出發頂點到i頂點距離進行比較
if (!visitedVertex.in(i) && length < visitedVertex.getDis(i)) {
visitedVertex.updateDis(i, length);
visitedVertex.updatePre(i, index);
}
}
}
public void showDjs() {
visitedVertex.showDjs();
}
}
//已訪問頂點集合
class VisitedVertex {
/**
* 記錄各個頂點是否訪問過1表示訪問過, 0未訪問,會動態更新
*/
public int[] already_arr;
/**
* 每個下標對應的值爲前- -個頂點下標,會動態更新
*/
public int[] pre_visited;
/**
* 記錄出發頂點到其他所有頂點的距離,比如G爲出發頂點,
* 就會記錄G到其它項點的距離,會動態更新,求的最短距離就會存放到dis|
*/
public int[] dis;
/**
* 構造器
*
* @param length 表示頂點的個數
* @param index 表示出發頂點的下標
*/
public VisitedVertex(int length, int index) {
this.already_arr = new int[length];
this.pre_visited = new int[length];
this.dis = new int[length];
// 初始化dis數組
Arrays.fill(dis, 65535);
// 設置index已經被訪問
already_arr[index] = 1;
// 設置出發頂點的訪問距離爲0
this.dis[index] = 0;
}
/**
* 功能:判斷index項點是否被訪問過
*
* @param index
* @return 如果訪問過, 就返回true, 否則訪問false
*/
public boolean in(int index) {
return already_arr[index] == 1;
}
/**
* ※
* 功能:更新出發頂點到index頂點的距離
*
* @param index
* @param len
*/
public void updateDis(int index, int len) {
dis[index] = len;
}
/**
* 功能:更新pre頂點的前驅頂點爲index結點
*
* @param pre
* @param index
*/
public void updatePre(int pre, int index) {
pre_visited[pre] = index;
}
/**
* 功能:返回出發頂點到index頂點的距離
*
* @param index
*/
public int getDis(int index) {
return dis[index];
}
/**
* 繼續訪問並返回新的訪問節點
*
* @return
*/
public int updateArr() {
int min = 65535, index = 0;
for (int i = 0; i < already_arr.length; i++) {
if (already_arr[i] == 0 && getDis(i) < min) {
min = getDis(i);
index = i;
}
}
// 更新index已經被訪問
already_arr[index] = 1;
return index;
}
public void showDjs() {
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int count = 0;
for (int i : dis) {
if (i != 65535) {
System.out.print(vertex[count] + "(" + dis[count] + ")");
} else {
System.out.print(vertex[count] + "(N)");
}
count ++;
}
System.out.println();
}
}