迪傑斯特拉算法 是求最短路徑方法的其中一種,這個有什麼做用呢?算法
有一張圖:數組
假設求G點到其餘各點的最小路徑。測試
是這樣來的。this
好比找到了和G點相鏈接全部點,ABED。這時候肯定GA是必定是最短的,爲何這麼說呢?G->A和G從別的點到A,一旦G走BED 必定會大於GA,後續就跟不可能大於了。code
因此GA爲最短,這時候就肯定了A。這時候開始從A點開始,找到和A點相連可是沒有肯定最短的點,有B、C。G->A->B 大於G->B。而後A能夠到C,這時候肯定G->C 是9。對象
而後從G到各點已經相連中,找到沒有確認的最小路徑,這個就是確認了G->B最短。爲何可以確認呢?由於G到A而後到B大於G->B,那麼能夠確認G到B最短,這是由於GA是最短的,從最短的到不了,其餘的必定大於G->B。blog
上面說其實有點模糊。get
是這樣的,若是從G爲出發點確認了n個點,那麼剩下的m個點怎麼確認呢?string
確定就是從G從到先到G最短的點,嘗試是否有其餘路,若是沒有,那麼就確認了。it
代碼以下:
class Program { private static int INF = int.MaxValue; static void Main(string[] args) { char[] vertex = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' }; int N = 65535;// 表示不能夠鏈接 int[,] matrix = { { N, 5, 7, N, N, N, 2 }, { 5, N, N, 9, N, N, 3 }, { 7, N, N, N, 8, N, N }, { N, 9, N, N, N, 4, N }, { N, N, 8, N, N, 5, 4 }, { N, N, N, 4, 5, N, 6 }, { 2, 3, N, N, 4, 6, N } }; //建立 Graph對象 Graph graph = new Graph(vertex, matrix); //測試, 看看圖的鄰接矩陣是否ok graph.showGraph(); //測試迪傑斯特拉算法 graph.dsj(2);//C graph.showDijkstra(); Console.Read(); } } class Graph { private char[] vertex;//頂點數組 private int[,] matrix;//鄰接矩陣 private VisitedVertex vv;//頂點狀態 public Graph(char[] vertex, int[,] matrix) { this.vertex = vertex; this.matrix = matrix; } public void showDijkstra() { vv.show(); } public void showGraph() { for (int i = 0; i < vertex.Length; i++) { for (int j = 0; j < vertex.Length; j++) { Console.Write(matrix[i, j] + " "); } Console.WriteLine(); } } public void dsj(int index) { vv = new VisitedVertex(vertex.Length, index); update(index); for (int i = 1; i < vertex.Length; i++) { index = vv.updateArr(); update(index); } } private void update(int index) { int len = 0; for (int j = 0; j < vertex.Length; j++) { len = vv.getDis(index) + matrix[index, j]; if (!vv.isVisited(j) && len < vv.getDis(j)) { vv.updatePre(j, index); vv.updateDis(j, len); } } } } class VisitedVertex { //記錄各個頂點的訪問狀態 public int[] already_arr; //每一個頂點對應前一個頂點的下標 public int[] pre_visited; //記錄出發點到其餘頂點的距離 public int[] dis; public VisitedVertex(int length, int index) { already_arr = new int[length]; pre_visited = new int[length]; dis = new int[length]; Array.Fill(dis, int.MaxValue); this.already_arr[index] = 1; this.dis[index] = 0; } public int updateArr() { int min = int.MaxValue, index = 0; for (int i = 0; i < already_arr.Length; i++) { if (already_arr[i] == 0 && dis[i] < min) { min = dis[i]; index = i; } } //更新 index 頂點被訪問過 already_arr[index] = 1; return index; } /// <summary> /// 是否訪問過 /// </summary> /// <param name="index">下標距離</param> /// <returns></returns> public Boolean isVisited(int index) { return already_arr[index] == 1; } //更新距離 public void updateDis(int index, int length) { dis[index] = length; } //更新前驅節點 public void updatePre(int index, int pre) { pre_visited[index] = pre; } //返回到某個節點的距離 public int getDis(int index) { return dis[index]; } //顯示最後的結果 //即將三個數組的狀況輸出 public void show() { Console.WriteLine("輸出前驅"); //輸出pre_visited foreach (int i in pre_visited) { Console.Write(i + " "); } Console.WriteLine(); char[] vertex = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' }; int count = 0; foreach (int i in dis) { if (i != 65535) { Console.Write(vertex[count] + "(" + i + ") "); } else { Console.Write("N "); } count++; } Console.WriteLine(); } }
結果: