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,...