每天學一點演算法-Dijkstra演算法__演算法

來源:互聯網
上載者:User
Dijkstra演算法


定義


戴克斯特拉演算法(Dijkstra’s algorithm)是由荷蘭電腦科學家艾茲赫爾·戴克斯特拉提出。迪科斯徹演算法使用了廣度優先搜尋解決非負權有向圖的單源最短路徑問題,演算法最終得到一個最短路徑樹。該演算法常用於路由演算法或者作為其他圖演算法的一個子模組。

  該演算法的輸入包含了一個有權重的有向圖 G,以及G中的一個來源頂點 S。我們以 V 表示 G 中所有頂點的集合。每一個圖中的邊,都是兩個頂點所形成的有序元素對。(u, v) 表示從頂點 u 到 v 有路徑相連。我們以 E 表示G中所有邊的集合,而邊的權重則由權重函數 w: E → [0, ∞] 定義。因此,w(u, v) 就是從頂點 u 到頂點 v 的非負權重(weight)。邊的權重可以想像成兩個頂點之間的距離。任兩點間路徑的權重,就是該路徑上所有邊的權重總和。已知有 V 中有頂點 s 及 t,Dijkstra 演算法可以找到 s 到 t的最低權重路徑(例如,最短路徑)。這個演算法也可以在一個圖中,找到從一個頂點 s 到任何其他頂點的最短路徑。對於不含負權的有向圖,Dijkstra 演算法是目前已知的最快的單源最短路徑演算法。


步驟


1.初始時令 S={V0},T={其餘頂點},T中頂點對應的距離值

  若存在<V0,Vi>,d(V0,Vi)為<V0,Vi>弧上的權值

  若不存在<V0,Vi>,d(V0,Vi)為∞

2.  從T中選取一個其距離值為最小的頂點W且不在S中,加入S

3.  對其餘T中頂點的距離值進行修改:若加進W作中間頂點,從 V0 到 Vi 的距離值縮短,則修改此距離值

  重複上述步驟2、3,直到S中包含所有頂點,即W=Vi 為止


理解


花了寶貴的一下午研究了演算法,遍曆所需。總結如下:

時間複雜度:執行演算法所需要的計算工作量

空間複雜度:執行演算法所需要的記憶體空間


T(n):時間複雜度,大O標識。

  時間複雜度T(n)按數量級遞增順序為:

常數階   對數階 線性階 線性對數階 平方階 立方階 …… K次方階 指數階
O(1)   O(log2n) O(n) O(nlog2n) O(n2) O(n3)   O(nk) O(2n)

複雜度低 ---->---->---->---->---->---->---->---->---->---->---->---->----> 複雜度高

S(n):空間複雜度。大O標識,空間的複雜度要上機實際運行才能知道。


有向圖非負權最短路徑演算法,時間複雜度O(n的平方)。

1.有2個儲存頂點的數組,S和U。S儲存已經已經獲得與起始點最短路徑的頂點。U中儲存剩下的沒有獲得最短距離的頂點。

2.遍曆開始:將起始點從U移到S中,然後遍曆U中頂點到起始點的距離,取最小的距離的頂點移到S中。然後以該頂點為中間點開始遍曆,意思就是:起始點A,然後發現了A->C的距離是A可到達的所有頂點中最小的距離,然後把C從U中移到S中,然後下一次遍曆就要以C為中間點A-C->莫個跟C鄰近的點。

3.計算剩下的頂點距起始點距離,如果存在S中直接可以到達的,比如A可以到達B,然後它的距離又比A-C-B(且是唯一一條從C為中間點)的距離要近,那麼A-B的最短距離要更新為a-b的權值,而不是A-C-B的權值。


而在程式中實現的時候是通過2維數組的形式儲存有向圖的資訊。例如A-C-B的儲存形式為,權值為2-1

int[][]  a = {{0,max,2},{max,0,max},{max,1,0}};

數組中的第一個元素表示A頂點,和自己的距離為0。與B因為不臨近,所以為無窮大。與C的距離為2

第二個元素表示B元素與A不臨近,與自己為0。與C不臨近。

第三個元素表示C與A不臨近,與B為1的距離,與自己為0。

然後我們將該數組做dijkstra遍曆。我們預設以A為標準點,也就是以A為起始點。

首先第一步將數組a的第一個元素儲存到map中。儲存已經獲得最近距離的點,和該距離的數值。map<索引,值>

剛開始map中的數值是這樣的<0,0><1,max><2,2>代表的就是各點與A的距離。然後我們會取距離最小的點,也就是起始點本身(距離為0),加入到儲存已得到最低距離的數組S中(List<interger> S=new ArrayList(interger))。至於第一步中的U數組,在編程中並沒有具體,而是儲存在原始的map中。

然後進入第三步的遍曆的狀態,因為第二步的轉移過程已經完成。第三步就是判斷A的鄰近點是否有比A到本身距離低的。(當然這是不可能的)它會遍曆二維數組的其他元素,將裡面的權值調出來和當前頂點與起始點的距離相加看是否還小於當前的距離。如果成立,那麼該節點的最低距離就會變為該值。

拋開上面A-C-B的限制,為了講的清楚,我假設如下圖:




剛開始,我遍曆A-C,A-B。然後A-C的距離近,我把C添加到S中。然後以C為中間節點A-C-B=3。發現比A-B的距離近,這時候我就更新map裡的值啦。<1,4>就要變為<1,3>。

將B添加到S中,以A-B遍曆剩下的頂點。

OY。爽。


時間複雜度


O(n^2)


摘錄別人的代碼,協助分析:


代碼






package com.spreadtrum.apptraverse.test;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map.Entry;import java.util.Set;public class ShortestPath {private static final int minDis = 0;private static final int maxDis = Integer.MAX_VALUE;// 圖的鄰接矩陣int[][] matrix;// 起始點int startIndex;// 用來存放起始點到其它點當前的距離HashMap<Integer, Integer> distanceMap = new HashMap<Integer, Integer>();// 用來存放已經找到最短路徑的點的集合Set<Integer> findedSet = new HashSet<Integer>();public ShortestPath(int[][] matrix, int start) {this.matrix = matrix;this.startIndex = start;// findedSet.add(startIndex);find();printDistance();}public void find() {// 用start相鄰的點初始化distanceMapfor (int i = 0; i < matrix.length; i++) {// if (matrix[startIndex][i] != maxDis)//i代表第幾個點,第二個參數代表到起始點的距離,第i個點到起始點的距離為matrix[startIndex][i]的值,也就是二維數組中一行裡的資料。distanceMap.put(i, matrix[startIndex][i]);}while (findedSet.size() != matrix.length) {//剩餘節點中距離起始點最近的距離的點int currentMinIndex = currentMinIndex();// 用此結點更新其它結點的距離for (int i = 0; i < matrix.length; i++) {//S數組中沒有該索引點,必須是當前點的鄰近點,當前距離+當前點與相鄰點的距離相加<i索引點的距離。if (!findedSet.contains(i) && matrix[currentMinIndex][i] != maxDis&& matrix[currentMinIndex][i] + distanceMap.get(currentMinIndex) < distanceMap.get(i))distanceMap.put(i, matrix[currentMinIndex][i] + distanceMap.get(currentMinIndex));}// 放入findedsetfindedSet.add(currentMinIndex);}}// 列印從起始點到所有點的最短距離public void printDistance() {Iterator<Entry<Integer, Integer>> it = distanceMap.entrySet().iterator();int min = Integer.MIN_VALUE;int minIndex = -1;while (it.hasNext()) {Entry<Integer, Integer> entry = it.next();System.out.println(startIndex + "---->" + entry.getKey() + ":" + entry.getValue());}}// 返回當前最小距離的點(必須不包含在findedSet中)private int currentMinIndex() {Iterator<Entry<Integer, Integer>> it = distanceMap.entrySet().iterator();int min = Integer.MAX_VALUE;int minIndex = -1;while (it.hasNext()) {Entry<Integer, Integer> entry = it.next();System.out.println("距起始點距離" + entry.getValue());if (!findedSet.contains(entry.getKey()) && entry.getValue() < min) {min = entry.getValue();minIndex = entry.getKey();}}System.out.println("=====");return minIndex;}public static void main(String[] args) {int[][] inputMatrix = new int[][] { { minDis, 2, maxDis, 1, maxDis, maxDis, maxDis },{ maxDis, minDis, maxDis, 3, 10, maxDis, maxDis }, { 4, maxDis, minDis, maxDis, maxDis, 5, maxDis },{ maxDis, maxDis, 2, minDis, 2, 8, 4 }, { maxDis, maxDis, maxDis, maxDis, minDis, maxDis, 6 },{ maxDis, maxDis, maxDis, maxDis, maxDis, minDis, maxDis },{ maxDis, maxDis, maxDis, maxDis, maxDis, 1, minDis } };ShortestPath path = new ShortestPath(inputMatrix, 0);/*path.find();path.printDistance();*/}}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.