Dijkstra算法詳解

Dijkstra算法詳解:https://blog.csdn.net/longshengguoji/article/details/10756003

在解決單源點(diǎn)最短路徑的問(wèn)題時(shí),常常用到經(jīng)典的Dijkstra算法,其算法的本質(zhì)思想是:按路徑長(zhǎng)度遞增依次產(chǎn)生最短路徑

下面給出算法的大致流程:

1.初始化所有結(jié)點(diǎn)并將起始點(diǎn)設(shè)為標(biāo)記,進(jìn)入以下循環(huán)

2.在到達(dá)某點(diǎn)的最短路徑中找最小且未標(biāo)記的點(diǎn)(可以用一維數(shù)組表示)

??如:

數(shù)組下標(biāo):0 ?1 ? 2 ? 3 ? 4 ? 5

? ?Len ? ? ?:- ? 0 ? 5 ?10 ?2 ? -

這個(gè)數(shù)組表示 1號(hào)節(jié)點(diǎn)為初始節(jié)點(diǎn),1號(hào)節(jié)點(diǎn)到達(dá)2號(hào)節(jié)點(diǎn)的最短路徑為5,到3號(hào)為10,無(wú)法到達(dá)5號(hào)(具體可以以較大的數(shù)表示其路徑)。

從中找到一個(gè)未標(biāo)記且Len最短的一個(gè),未標(biāo)記用另一數(shù)組記錄

如:

數(shù)組下標(biāo):0 ? 1 ? 2 ? 3 ? 4 ? 5

? ?標(biāo)記 ? ? :0 ? 1 ? 0 ? 0 ? 1 ? 0

此數(shù)組表示從初始節(jié)點(diǎn)到達(dá)4號(hào)節(jié)點(diǎn)的最短路徑已找到

從以上兩個(gè)數(shù)組中可以得出:此次循環(huán)找到的點(diǎn)為2號(hào)節(jié)點(diǎn),進(jìn)入下一步

3.標(biāo)記找到的點(diǎn),以此標(biāo)記點(diǎn)為中間點(diǎn)重新計(jì)算所有未標(biāo)記點(diǎn)的最短路徑(更新最短路徑表)

4.循環(huán)1.2步至n-1次(n為頂點(diǎn)數(shù),若最后還有未被標(biāo)記的,說(shuō)明無(wú)法到達(dá)此點(diǎn))

下面是核心代碼:

[cpp]?view plain?copy

while(count

??????{??

??????????tempmin=INFINITE;??

for(i=1;i<=n;i++)??

??????????{??

if(in[i]==0&&Len[i]

??????????????{??

??????????????????tempmin=Len[i];??

??????????????????si=i;??

??????????????}??

??????????}??

??????????in[si]=1;??

??????????count++;??

for(i=1;i<=n;i++)?//updata?the?length??

??????????{??

if(in[i]==0&&(tempmin+mGraph.matrix[si][i])

??????????????{??

??????????????????Len[i]=tempmin+mGraph.matrix[si][i];??

??????????????}??

??????????}??????

??????}??

核心部分是上面的兩個(gè)for循環(huán),第一個(gè)for循環(huán)遍歷所有結(jié)點(diǎn),找到未標(biāo)記并且長(zhǎng)度最短的路徑;第二個(gè)for循環(huán)也是遍歷所有結(jié)點(diǎn)以上面找到的最短路徑結(jié)點(diǎn)為中間點(diǎn)更新最短路徑表;注意在第一個(gè)for循環(huán)之后要標(biāo)記找到的點(diǎn)(說(shuō)明到達(dá)此點(diǎn)的最短路徑已找到)

下面用一個(gè)實(shí)例來(lái)具體說(shuō)明:

若有這樣一張有向圖(此圖為《數(shù)據(jù)結(jié)構(gòu)》嚴(yán)蔚敏 p188頁(yè),書中沒(méi)有詳細(xì)講解,現(xiàn)以此為實(shí)例)

V0-V5 共6個(gè)節(jié)點(diǎn),節(jié)點(diǎn)間路徑已標(biāo)出,現(xiàn)要求從V0到其余各節(jié)點(diǎn)的最短路徑;

有上面的算法流程可知,在使用Dijkstra算法時(shí)需要幾個(gè)結(jié)構(gòu)來(lái)保存我們想要的信息:

1.保存這張圖的結(jié)構(gòu)體

2.記錄V0到其余各節(jié)點(diǎn)最短路徑的數(shù)組(這里設(shè)為L(zhǎng)en[n+1])

3.記錄某節(jié)點(diǎn)是否已找到最短路徑的數(shù)組(這里設(shè)為in[n+1])

接下來(lái)就是算法實(shí)現(xiàn)部分:

1.標(biāo)記V0 -- in[1]=1 ? 初始化 Len[]={INFINITE , 0 , INFINITE , 10, INFINITE , 30 , 100} ?這里數(shù)組首元素未用到,數(shù)組下標(biāo)從1開始表示V0以此類推

2.第一次循環(huán)與V0相鄰的有V2、V4、V5,其中V2距離最短為10,標(biāo)記V2,并且以V2為中間點(diǎn)(路徑為V0->V2->Vx)更新最短路表,此時(shí)V3被更新為10+50=60,。

3.進(jìn)入第二次循環(huán),此時(shí)未被標(biāo)記的有V1、V3、V4、V5,,其中從V0到這些的臨時(shí)最短路分別為INFINITE、60、30、100,從中找到最小的即V4,將V4標(biāo)記為1,以V4為中間點(diǎn)(路徑為V0->V4->Vx)更新最短路表,此時(shí)V3被更新為50,V5被更新為90。

4.進(jìn)入第三次循環(huán),此時(shí)未被標(biāo)記的有V1、V3、V5,其中臨時(shí)最短路分別為INFINITE、50、90,從中找到最小的即V3,將V3標(biāo)記為1,以V3為中間點(diǎn)(路徑為V0->V4->V3->Vx)更新最短路表,此時(shí)V5被更新成60。

5.進(jìn)入第四次循環(huán),此時(shí)未被標(biāo)記的有V1、V5,其中臨時(shí)最短路分別為INFINITE、60,找到V5,標(biāo)記為1,以V5為中間點(diǎn)更新最短路表,此時(shí)沒(méi)有元素被更新

6.進(jìn)入第五次循環(huán),這次循環(huán)沒(méi)找到任何東西

7.退出循環(huán),Len表中即為V0到其余各個(gè)節(jié)點(diǎn)的最短路徑。

以上就是Dijkstra算法最基本的思想,當(dāng)然,在找最短路時(shí)我們常常會(huì)需要求出到達(dá)某點(diǎn)的最短路徑,那么下面,我們就來(lái)看看要怎樣記錄下到達(dá)某點(diǎn)的最短路徑:

在Dijkstra算法的前提下加入查詢最短路徑其實(shí)很簡(jiǎn)單,只要在每次更新最短路時(shí)保存在該頂點(diǎn)的父節(jié)點(diǎn)序號(hào)即可,最后輸出時(shí)回退中間節(jié)點(diǎn)然后用堆棧輸出即可

最后直接給出完整代碼(寫的很一般,還望指教):

[cpp]?view plain?copy

#include???

#include???

#define?MAX_LEN?100??

#define?INFINITE?1000??

typedef?struct?graph??

{??

int?nodenum;??

int?edgenum;??

int?matrix[MAX_LEN][MAX_LEN];??

}Graph;??


typedef?struct?stack??

{??

int??bottom;??

int??top;??

int??printout[MAX_LEN];??

}mstack;??


int?in[MAX_LEN];??

int?Len[MAX_LEN];??

int?path[MAX_LEN];??


void?InitStack(mstack?*s)??

{??

????s->bottom=0;??

????s->top=0;??

memset(s->printout,0,sizeof(int)*MAX_LEN);??

}??


void?push(mstack?*s,int?m)??

{??

????s->printout[s->top++]=m;??

}??


int?pop(mstack?*s)??

{??

return?s->printout[--s->top];??

}??


void?InitGraph(Graph?*g,int?n)??

{??

int?i,j;??

for(i=1;i<=n;i++)??

for(j=1;j<=n;j++)??

??????????{??

if(i==j)g->matrix[i][j]=0;??

else?g->matrix[i][j]=INFINITE;???????

??????????}??


for(i=1;i<=n;i++)??

?????{??

?????????in[i]=0;??

?????????Len[i]=INFINITE;??

?????????path[i]=0;??

?????}??

}??


int?main()??

{??


int?n,m,i,A,B,templen,count,min,tempmin,si,temp;??

while(scanf("%d?%d",&n,&m))??

????{??

????????count=0;??

????????Graph?mGraph;??

????????mGraph.edgenum=m;??

????????mGraph.nodenum=n;??

????????InitGraph(&mGraph,n);??

for(i=0;i

????????{??

scanf("%d?%d?%d",&A,&B,&templen);??

????????????mGraph.matrix[A][B]=templen;??

????????}??



????????in[1]=1;??

path[1]=1;//sava?path??

????????Len[1]=0;??


for(i=2;i<=n;i++)??

????????{??

Len[i]=mGraph.matrix[1][i];//Init?the?len??

if(Len[i]!=INFINITE)path[i]=1;??

????????}??


????????min=0;??

????????si=1;??


while(count

????????{??

????????????tempmin=INFINITE;??

for(i=1;i<=n;i++)??

????????????{??

if(in[i]==0&&Len[i]

????????????????{??

????????????????????tempmin=Len[i];??

????????????????????si=i;??

????????????????}??

????????????}??

????????????in[si]=1;??


for(i=1;i<=n;i++)?//updata?the?length??

????????????{??

if(in[i]==0&&(tempmin+mGraph.matrix[si][i])

????????????????{??

????????????????????Len[i]=tempmin+mGraph.matrix[si][i];??

????????????????????path[i]=si;??

????????????????}??

????????????}??

????????????count++;???

????????}??


????????mstack?s;??

for(i=1;i<=n;i++)??

????????{??

????????????temp=i;??

????????????InitStack(&s);??

if(path[temp]==0)??

????????????{???

printf("no?path\n");??

continue;??

????????????}??

while(path[temp]!=1)??

????????????{??

????????????????push(&s,path[temp]);??

????????????????temp=path[temp];??

????????????}??

printf("1-->");??

while(s.bottom!=s.top)??

????????????{??

printf("%d-->",pop(&s));??

????????????}??

printf("%d??min?length?is?%d\n",i,Len[i]);??


????????}??


????}??

return?0;??

}??

附上上面那張圖的結(jié)果(V0節(jié)點(diǎn)為1,V1節(jié)點(diǎn)為2.。。。以此類推)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容