演算法導論 第24章 Dijkstra演算法

2021-06-26 21:28:56 字數 2524 閱讀 4577

dikstra演算法解決的是有向圖上單源最短路徑問題(無向圖可以看成有相反的兩條有向邊),且要求邊的權重都是非負值(如果有負權,已經確定的最短路徑到v點有可能會被右面發現的點有條負權值的邊到v點而導致v點的最短路徑不成立)。

演算法導論用了很多引理,性質來證明dijstra演算法的正確性,這裡不說了,也表達不明白,只說我理解的過程。

有乙個圖g( v,e) ,選定乙個源點s,維護乙個集合q=v-s,  q中點有乙個d值表示此時從s到該點的已知距離,s.d=0 ;初始化都為正無窮,表明不可達。然後對s點所連線的點(設為點集m)進行鬆弛操作,就是設點m屬於m,

m.d > s.d+ w(s,m) 則更新 m.d=s.d+w(s,m)  將其慢慢收斂。

q中的點能夠鬆弛的鬆弛完之後,取出此時d值最小的點的,把它看成上面的s點,對其所連線點的進行鬆弛操作,然後再取點,重複直到q集合為空。s點到所有點的最短路徑就找到了。

再來說說實現的問題:

1.q集合用陣列來實現,我在實現的時候q陣列存在的是對應點的d值,如果這個點已經被取出則變為1;這樣所有的開銷都在去最小值上了,因為每次都要掃瞄整個陣列。取點要v次,一次掃瞄o(v) ,所以總執行時間o(v^2);

2.q集合用優先佇列實現,但是因為要有decrease-key操作,所以貌似不能用標準庫的優先佇列。所以只能自己實現乙個最小堆的優先佇列。因為鬆弛的時候是找到點,然後又要去更改q中的對應點的d值,然後在進行調整,所以要有互相指向的控制代碼。

取點v次,每次extract-min花費o(lgv)

decrease-key e次    ,每次花費 o(lgv)

總花費           o( (e+v)lgv )

陣列方法的時候,**不貼出來來了,帶控制代碼的數組建最小優先佇列的方法我貼出來,其實控制代碼就是乙個指向元素在陣列堆中的位置,因為要建堆,維護堆,取出最小值等操作會因為位置變化,所以要在幾個操作裡面更新控制代碼。

dijkstra.cpp

#include#include#include#include"minipriorityqueue.h"

using namespace std;

//dijkstra演算法解決的是帶權重的單源最短路徑問題,要求所有邊的權重都是非負值

//圖的結構,點的結構,檢視.h檔案。

//最小堆的結構實現也在.h檔案

void printgraph(graph g)

cout

while(s.size()!=g.n)

}}cout<

minipriorityqueue.h:

#ifndef minipriorityqueue_h_included

#define minipriorityqueue_h_included

#include#include#includeusing namespace std;

class node

int adjvex;

int weight; //鄰接鍊錶結點直接帶權重值

node *nextvex;

};class vex

;typedef node * adjnode;

class graph

;void creategraph(graph &g)

++ex;

ne->adjvex=x;

ne->weight=w;

}//while}}

class minipriorityqueue

}void minheapfix(int i,graph &g); //維護堆的性質

void buildminheap(graph &g);//建堆

void decreasekey(int j,int k,graph &g); //更新d值

vex extractmin(graph &g)

public:

vex* q;

int length;

};void minipriorityqueue::decreasekey(int j,int k,graph &g)

}void minipriorityqueue::minheapfix(int i,graph &g)

}#endif // minipriorityqueue_h_included

我的圖建立重定向了:

test.txt:

52 10 4 5 -1 -1

3 1 4 2 -1 -1 

5 4 -1 -1 

2 3 3 9 5 2 -1 -1 

3 6 1 7 -1 -1

圖的:

s=1   ,t=2  ,x=3 , y=4 ,z =5

執行結果:

最後我們可以發現,廣度優先演算法其實就是dijkstra演算法的簡化,其中邊的權重全部變為1,q佇列用先進先出佇列實現,

《演算法導論》第24章 單源最短路徑

單元最短路徑問題 單源最短路徑問題,試 決從乙個原點到圖中其他所有點的最短路徑問題。此問題的變體有單終點最短路徑問題,單終點最短路徑問題和每對頂點間最短路徑問題。可以相應理解為一對多 多對 一 一對一和多對多的對映關係。負權值邊和負權迴路 某些權值可以是負的,這些邊稱為是負權值邊。負權迴路指的是構成...

《演算法導論》第24章 單源最短路徑

最短路徑的最優子結構 最短路徑的子路徑也是最短路徑。負權重的邊 權重為負數的邊。我的理解 大概知道這個就可以了 環路 最短路徑既不能包含正的環路,也不能包含負的環路。正的環路,我覺得正常人想走最短的路,都不會在那裡打圈,除非路就是圓的 負環路你多繞幾圈,最後權重想變多小變多小,就很沒意思。最短路徑的...

演算法導論 第5章

這一章,說來說去,兩件事情,1.概率分析。2.隨機演算法。先把這個僱傭問題拿出來。問題 有一批參與面試的人,你要乙個個面試 面試每個人都要花費c1 如果當前面試者比自己的助理能力強,則辭掉當前助理的,並把當前面試者提拔為助理 僱傭乙個人要花費c2 一直面試完所有人。這裡考慮的是面試所花的money,...