[資料結構]迪傑斯特拉(Dijkstra)演算法

來源:互聯網
上載者:User

標籤:detail   oid   頂點   ima   bre   blank   break   lan   資料   

基本思想

     通過Dijkstra計算圖G中的最短路徑時,需要指定起點vs(即從頂點vs開始計算)。

     此外,引進兩個集合S和U。S的作用是記錄已求出最短路徑的頂點,而U則是記錄還未求出最短路徑的頂點(以及該頂點到起點vs的距離)。

     初始時,S中只有起點vs;U中是除vs之外的頂點,並且U中頂點的路徑是"起點vs到該頂點的路徑"。然後,從U中找出路徑最短的頂點,並將其加入到S中;接著,更新U中的頂點和頂點對應的路徑。 然後,再從U中找出路徑最短的頂點,並將其加入到S中;接著,更新U中的頂點和頂點對應的路徑。 ... 重複該操作,直到遍曆完所有頂點。

操作步驟

(1) 初始時,S只包含起點vs;U包含除vs外的其他頂點,且U中頂點的距離為"起點vs到該頂點的距離"[例如,U中頂點v的距離為(vs,v)的長度,然後vs和v不相鄰,則v的距離為∞]。

(2) 從U中選出"距離最短的頂點k",並將頂點k加入到S中;同時,從U中移除頂點k。

(3) 更新U中各個頂點到起點vs的距離。之所以更新U中頂點的距離,是由於上一步中確定了k是求出最短路徑的頂點,從而可以利用k來更新其它頂點的距離;例如,(vs,v)的距離可能大於(vs,k)+(k,v)的距離。

(4) 重複步驟(2)和(3),直到遍曆完所有頂點。

 

接下來做一個簡單例子求解:

 

 

package com.darrenchan.graph;import java.util.ArrayList;import java.util.List;public class ShortestPathDijkstra {    /** 鄰接矩陣 */    private int[][] matrix;    /** 表示正無窮 */    private int MAX_WEIGHT = Integer.MAX_VALUE;    /** 頂點集合 */    private String[] vertexes;    /**     * 建立圖     */    private void createGraph(int index) {        matrix = new int[index][index];        vertexes = new String[index];        int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };        int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };        int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };        int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT };        int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT };        int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT };        int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 };        int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 };        int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0 };        matrix[0] = v0;        matrix[1] = v1;        matrix[2] = v2;        matrix[3] = v3;        matrix[4] = v4;        matrix[5] = v5;        matrix[6] = v6;        matrix[7] = v7;        matrix[8] = v8;        vertexes[0] = "v0";        vertexes[1] = "v1";        vertexes[2] = "v2";        vertexes[3] = "v3";        vertexes[4] = "v4";        vertexes[5] = "v5";        vertexes[6] = "v6";        vertexes[7] = "v7";        vertexes[8] = "v8";    }    /**     * Dijkstra最短路徑。     *     * vs -- 起始頂點(start vertex) 即,統計圖中"頂點vs"到其它各個頂點的最短路徑。     */    public void dijkstra(int vs) {        // flag[i]=true表示"頂點vs"到"頂點i"的最短路徑已成功擷取        boolean[] flag = new boolean[vertexes.length];        // U則是記錄還未求出最短路徑的頂點(以及該頂點到起點s的距離),與 flag配合使用,flag[i] == true 表示U中i頂點已被移除        int[] U = new int[vertexes.length];        // 前驅頂點數組,即,prev[i]的值是"頂點vs"到"頂點i"的最短路徑所經曆的全部頂點中,位於"頂點i"之前的那個頂點。        int[] prev = new int[vertexes.length];        // S的作用是記錄已求出最短路徑的頂點        String[] S = new String[vertexes.length];        // 步驟一:初始時,S中只有起點vs;U中是除vs之外的頂點,並且U中頂點的路徑是"起點vs到該頂點的路徑"。        for (int i = 0; i < vertexes.length; i++) {            flag[i] = false; // 頂點i的最短路徑還沒擷取到。            U[i] = matrix[vs][i]; // 頂點i與頂點vs的初始距離為"頂點vs"到"頂點i"的權。也就是鄰接矩陣vs行的資料。            prev[i] = 0; //頂點i的前驅頂點為0        }        // 將vs從U中“移除”(U與flag配合使用)        flag[vs] = true;        U[vs] = 0;        // 將vs頂點加入S        S[0] = vertexes[vs];        // 步驟一結束        //步驟四:重複步驟二三,直到遍曆完所有頂點。        // 遍曆vertexes.length-1次;每次找出一個頂點的最短路徑。        int k = 0;        for (int i = 1; i < vertexes.length; i++) {            // 步驟二:從U中找出路徑最短的頂點,並將其加入到S中(如果vs頂點到x頂點還有更短的路徑的話,那麼            // 必然會有一個y頂點到vs頂點的路徑比前者更短且沒有加入S中            // 所以,U中路徑最短頂點的路徑就是該頂點的最短路徑)            // 即,在未擷取最短路徑的頂點中,找到離vs最近的頂點(k)。            int min = MAX_WEIGHT;            for (int j = 0; j < vertexes.length; j++) {                if (flag[j] == false && U[j] < min) {                    min = U[j];                    k = j;                }            }            //將k放入S中            S[i] = vertexes[k];            //步驟二結束            //步驟三:更新U中的頂點和頂點對應的路徑            //標記"頂點k"為已經擷取到最短路徑(更新U中的頂點,即將k頂點對應的flag標記為true)            flag[k] = true;            //修正當前最短路徑和前驅頂點(更新U中剩餘頂點對應的路徑)            //即,當已經"頂點k的最短路徑"之後,更新"未擷取最短路徑的頂點的最短路徑和前驅頂點"。            for (int j = 0; j < vertexes.length; j++) {                //以k頂點所在位置連線其他頂點,判斷其他頂點經過最短路徑頂點k到達vs頂點是否小於目前的最短路徑,是,更新入U,不是,不做處理                int tmp = (matrix[k][j] == MAX_WEIGHT ? MAX_WEIGHT : (min + matrix[k][j]));                if (flag[j] == false && (tmp < U[j])) {                    U[j] = tmp;                    //更新 j頂點的最短路徑前驅頂點為k                    prev[j] = k;                }            }            //步驟三結束        }        //步驟四結束        // 列印dijkstra最短路徑的結果        System.out.println("起始頂點:" + vertexes[vs]);        for (int i = 0; i < vertexes.length; i++) {            System.out.print("最短路徑(" + vertexes[vs] + "," + vertexes[i] + "):" + U[i] + "  ");            List<String> path = new ArrayList<>();            int j = i;            while (true) {                path.add(vertexes[j]);                if (j == 0)                    break;                j = prev[j];            }            for (int x = path.size()-1; x >= 0; x--) {                if (x == 0) {                    System.out.println(path.get(x));                } else {                    System.out.print(path.get(x) + "->");                }            }        }        System.out.println("頂點放入S中的順序:");        for (int i = 0; i< vertexes.length; i++) {            System.out.print(S[i]);            if (i != vertexes.length-1)                System.out.print("-->");        }    }    public static void main(String[] args) {        ShortestPathDijkstra dij = new ShortestPathDijkstra();        dij.createGraph(9);        dij.dijkstra(0);    }}

 

參考:56839285

[資料結構]迪傑斯特拉(Dijkstra)演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.