迪杰斯特拉算法(Dijkstra)
迪杰斯特拉算法是求最短路径的算法,计算图中一个顶点到其他顶点的最短路径,应用了广度优先的思想,由一个点扩散直到终点为止
过程:
设置出发顶点为v,集合为V,距离集合为Dis
从Dis中选取最小值移除di,同时移除对应的V的顶点vi
比较v到V中顶点的距离值,与v通过的vi到集合V中顶点的距离值,保留最小的
重复执行,直到最短路径顶点为目标顶点即可结束
import java.beans.VetoableChangeListenerProxy; import java.util.Arrays; public class DijkstraAlgorithm { public static void main(String[] args) { char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; int[][] matrix = new int[vertexs.length][vertexs.length]; final int N = 65535; matrix[0] = new int[]{N, 5, 7, N, N, N, 2}; matrix[1] = new int[]{5, N, N, 9, N, N, 3}; matrix[2] = new int[]{7, N, N, N, 8, N, N}; matrix[3] = new int[]{N, 9, N, N, N, 4, N}; matrix[4] = new int[]{N, N, 8, N, N, 5, 4}; matrix[5] = new int[]{N, N, N, 4, 5, N, 6}; matrix[6] = new int[]{2, 3, N, N, 4, 6, N}; Graph graph = new Graph(vertexs, matrix); graph.showGraph(); graph.dsj(6); graph.shouDijkstra(); } } class Graph { private char[] vertexs;//顶点 private int[][] matrix;//邻接矩阵 private VisitedVertex vv;//已经访问顶点的集合 public Graph(char[] vertexs, int[][] matrix) { this.vertexs = vertexs; this.matrix = matrix; } /** * 显示 */ public void showGraph() { for (int[] link : matrix) { System.out.println(Arrays.toString(link)); } } /** * 迪杰斯特拉算法实现 * * @param index 出发顶点对应下标 */ public void dsj(int index) { vv = new VisitedVertex(vertexs.length, index); update(index);//更新 index 顶点到周围顶点的距离和前驱顶点 for (int j = 1; j < vertexs.length; j++) { index = vv.updateArr();//选择并返回新的访问顶点 update(index);//更新 index 顶点到周围顶点的距离和前驱顶点 } } private void update(int index) { int len = 0; for (int j = 0; j < matrix[index].length; j++) { //出发顶点到 index 顶点的距离 + 从 index 顶点到 j 顶点的距离的和 len = vv.getDis(index) + matrix[index][j]; //j 没有被访问过 并且 len 小于出发顶点到 j 顶点的距离 if (!vv.in(j) && len < vv.getDis(j)) { vv.updatePre(j, index);//更新 j 顶点的前驱为 index 顶点 vv.updateDis(j, len);//更新出发顶点到 j 顶点的距离 } } } public void shouDijkstra() { vv.show(); } } /** * 已访问集合 */ class VisitedVertex { //记录是否访问 1 访问 0 未访问 public int[] already_arr; //没个下标对应的值为前一个顶点的下标 public int[] pre_visited; //记录出发顶点到其他所有顶点的距离 public int[] dis; /** * 构造器 * * @param lenght 表示顶点的个数 * @param index 出发顶点对应的下标 */ public VisitedVertex(int lenght, int index) { this.already_arr = new int[lenght]; this.pre_visited = new int[lenght]; this.dis = new int[lenght]; //初始化 dis 数组 Arrays.fill(dis, 65535); this.already_arr[index] = 1; this.dis[index] = 0;//设置出发顶点的访问局距离为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 * @return */ 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 && dis[i] < min) { min = dis[i]; index = i; } } already_arr[index] = 1; return index; } /** * 显示最后结果 */ public void show() { System.out.println("======================"); for (int i : already_arr) { System.out.print(i + " "); } System.out.println(); for (int i : pre_visited) { System.out.print(i + " "); } System.out.println(); for (int i : dis) { System.out.print(i + " "); } System.out.println(); char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; int count = 0; for (int i : dis) { if (i != 65535) { System.out.print(vertex[count] + "(" + i + ") "); } else { System.out.print("N"); } count++; } System.out.println(); } }
这个算法不太好理解,建议尽量避免
根据自我理解改写

浙公网安备 33010602011771号