Dijkstra 單源最短路徑

java實現Dijkstra算法

源代碼
圖的結構Java實現

Dijkstra

public class Dijkstra {
    private static final int INF = Integer.MAX_VALUE;

    /**
     * 初始化距離矩陣
     *
     * @param graph 圖
     * @return 距離矩陣
     */
    private static int[][] initDistance(GraphMatrix graph) {
        int vertexNum = graph.getVertexNum();
        int[][] result = new int[vertexNum][vertexNum];
        // 初始化距離矩陣
        for (int i = 0; i < vertexNum; i++) {
            for (int j = 0; j < vertexNum; j++) {
                result[i][j] = graph.edges[i][j];
                if (i != j && result[i][j] == 0) {
                    result[i][j] = INF;
                }
            }
        }
        return result;
    }

    private static void showInfo(int[] dist, int[] prev) {
        System.out.print("距離向量 dist:");
        for (int val : dist) {
            if (val == INF) {
                System.out.printf("%4s ", "INF");
            } else {
                System.out.printf("%4d ", val);
            }
        }
        System.out.print("\n前驅結點 prev:");
        for (int val : prev) {
            System.out.printf("%4d ", val);
        }
        System.out.println();
    }

    private static void dijkstra(GraphMatrix<String> graph, String value) {
        dijkstra(graph, graph.getVertexIndex(value));
    }

    //計算一個頂點到其它一個頂點的最短距離
    public static void dijkstra(GraphMatrix graph, int v0) {
        int vertexNum = graph.getVertexNum();
        boolean[] visited = new boolean[vertexNum];
        int[][] distance = initDistance(graph);
        int[] dist = new int[vertexNum];
        int[] prev = new int[vertexNum];
        //初始化visited、dist和path
        for (int i = 0; i < vertexNum; i++) {
            //一開始假定取直達路徑最短
            dist[i] = distance[v0][i];
            visited[i] = false;
            //直達情況下的最後經由點就是出發點
            if (i != v0 && dist[i] < INF)
                prev[i] = v0;
            else
                prev[i] = -1; //無直達路徑
        }
        //初始時源點v0∈visited集,表示v0 到v0的最短路徑已經找到
        visited[v0] = true;
        // 下來假設經由一個點中轉到達其餘各點,會近些,驗證之
        // 再假設經由兩個點中轉,會更近些,驗證之,.....
        // 直到窮舉完所有可能的中轉點
        int minDist;
        int v = 0;
        //除了v0,剩下vertexNum - 1個結點
        for (int i = 0; i < vertexNum - 1; i++) {
            showInfo(dist, prev);
            //挑一個距離最近經由點,下標裝入 v
            minDist = INF;
            for (int j = 0; j < vertexNum; j++) {
                if (!visited[j] && dist[j] < minDist) {
                    v = j;// 經由頂點j中轉則距離更短
                    minDist = dist[j];
                }
            }
            visited[v] = true;
            /*頂點v併入S,由v0到達v頂點的最短路徑爲min.
              假定由v0到v,再由v直達其餘各點,更新當前最後一個經由點及距離*/
            for (int j = 0; j < vertexNum; j++) {
                if (!visited[j] && distance[v][j] < INF) {
                    if (minDist + distance[v][j] < dist[j]) {
                        //如果多經由一個v點到達j點的 最短路徑反而要短,就更新
                        dist[j] = minDist + distance[v][j];
                        //經由點的序號
                        prev[j] = v;
                    }
                }
            }
        }
        printPath(graph, v0, dist, prev);
    }

    //v0爲出發節點
    private static void printPath(GraphMatrix graph, int v0, int[] dist, int[] prev) {
        //由於記錄的中途節點是倒序的,所以使用棧(先進後出),獲得正序
        LinkedList<Integer> stack = new LinkedList<>();
        //打印從出發節點到各節點的最短距離和經過的路徑
        for (int i = 0; i < graph.getVertexNum(); i++) {
            int j = i;
            //如果j有中途節點
            while (prev[j] != -1) {
                stack.push(j);          //將j壓入堆
                j = prev[j];          //將j的前箇中途節點賦給j
            }
            stack.push(j);

            System.out.print(graph.vertexList.get(v0) + "-->" +
                    graph.vertexList.get(i) + " 的最短路徑是:" + dist[i]);
            System.out.print(", ");
            //先進後出,獲得正序
            while (!stack.isEmpty()) {
                System.out.print(graph.vertexList.get(stack.pop()));//打印堆的頭節點
                if (!stack.isEmpty()) {
                    System.out.print("->");
                }
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        GraphMatrix<String> graph = new GraphMatrix<>("ABCD");
        graph.type = GraphMatrix.GraphType.DIRECTED_GRAPH;
        graph.addEdge("A", "B", 1);
        graph.addEdge("A", "C", 2);
        graph.addEdge("A", "D", 3);
        graph.addEdge("B", "A", 4);
        graph.addEdge("C", "B", 5);
        graph.addEdge("C", "D", 1);
        graph.addEdge("D", "B", 1);
        graph.addEdge("D", "C", 2);
        graph.information();
        dijkstra(graph, "B");
    }
}

log

距離向量 dist:   4    0  INF  INF 
前驅結點 prev:   1   -1   -1   -1 
距離向量 dist:   4    0    6    7 
前驅結點 prev:   1   -1    0    0 
距離向量 dist:   4    0    6    7 
前驅結點 prev:   1   -1    0    0 
B-->A 的最短路徑是:4, B->A
B-->B 的最短路徑是:0, B
B-->C 的最短路徑是:6, B->A->C
B-->D 的最短路徑是:7, B->A->D
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章