迪杰斯特拉算法 是求最短路径方法的其中一种,这个有什么做用呢?算法
有一张图:数组
假设求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(); } }
结果: