日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】dijkstra算法

發布時間:2025/3/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】dijkstra算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【轉】dijkstra算法

來自:https://blog.csdn.net/tw_345/article/details/50109375#comments 2015年11月30日 10:55:08 閱讀數:1241

說到dijkstra,它其實是我第一個公司的Wi-Fi密碼,當時我還不知道它就是求最短路徑的一個算法。今天有幸能領略這位荷蘭科學家的智慧~

Dijkstra算法是求某個源點到其他各頂點的最短路徑的。

書本上的公式有點復雜,不如先看個例子再去理解公式~

?

比如上圖這道題(ppt畫的,湊合看吧~)

運用dijkstra,求V0到各點的最短路徑?

?

解答具體過程:

令S表示已求出最短路徑的頂點集合。D[i]表示V0到Vi的路徑長度。arcs[i][j]表示從i到j的直接距離

第一步:V0到其他頂點的直接路徑:

?

SD[1]D[2]D[3]D[4]D[5]
{V0}501045

下一步:計算min{D[i]},得到D[2]最小,便將V2加入S中,得到V0V2最短路徑10,重新計算V0到各點路徑:

D[1](new) = min{D[1](old) ,D[2]+arcs[2][1]} = min{50,10+∞}=50

D[3](new) = min{D[3](old) ,D[2]+arcs[2][3]} = min{∞,10+15}=25

D[4](new) = min{D[4](old) ,D[2]+arcs[2][4]} = min{45,10+∞}=45

D[5](new) = min{D[5](old) ,D[2]+arcs[2][5]} = min{∞,10+∞}=∞

得到

SD[1]D[2]D[3]D[4]D[5]
{V0,V2}502545

下一步:(也不能說下一步,反正就是循環)計算min{D[i]},D[3]最小,V3加入S中,得到V0V3最短路徑25,重新計算路徑:

D[1](new) = min{D[1](old) ,D[3]+arcs[3][1]} = min{50,25+20}=45

D[4](new) = min{D[4](old) ,D[3]+arcs[3][4]} = min{45,25+20}=45

D[5](new) = min{D[5](old) ,D[3]+arcs[3][5]} = min{∞,25+∞}=∞

得到

SD[1]D[2]D[3]D[4]D[5]
{V0,V2,V3}4545

怎么樣?是不是很帶感

下一步:計算min{D[i]},D[1](看1比較順眼)最小,V1加入S中,得到V0V1最短路徑45,重新計算路徑:

D[4](new) = min{D[4](old) ,D[1]+arcs[1][4]} = min{45,45+10}=55

D[5](new) = min{D[5](old) ,D[1]+arcs[1][5]} = min{∞,45+∞}=∞

得到

SD[1]D[2]D[3]D[4]D[5]
{V0,V2,V3,V1}45

下一步:計算min{D[i]},D[4]最小,V4加入S中,得到V0V4最短路徑45,重新計算路徑:

D[5](new) = min{D[5](old) ,D[4]+arcs[4][5]} = min{∞,45+∞}=∞

得到

SD[1]D[2]D[3]D[4]D[5]
{V0,V2,V3,V1,V4}

得到V0V5最短路徑∞,

所以最短路徑為

?

V0V145
V0V210
V0V325
V0V445
V0V5

Dijkstra算法的基本思想是:按最短路徑長度遞增的順序,逐個產生各最短路徑。

那么如何遞增呢?其實是運用一條性質:如果存在一條從i到j的最短路徑(Vi.....Vk,Vj),Vk是Vj前面的一頂點。那么(Vi...Vk)也必定是從i到k的最短路徑。

然而這條性質是如何得到呢,這就需要我們先弄清楚最短路徑的“最優子結構性質”。

最優子結構性質:如果P(i,j)={Vi....Vk..Vs...Vj}是從頂點i到j的最短路徑,k和s是這條路徑上的一個中間頂點,那么P(k,s)必定是從k到s的最短路徑。下面用反證法證明:

假設P(i,j)={Vi....Vk..Vs...Vj}是從頂點i到j的最短路徑,則有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而P(k,s)不是從k到s的最短距離,那么

必定存在另一條從k到s的最短路徑P'(k,s),那么P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。則與P(i,j)是從i到j的最短路徑相矛盾。因此該性質得證。

?

好了,鋪墊的差不多了,Dijkstra就提出了以最短路徑長度遞增,逐次生成最短路徑的算法。譬如對于源頂點V0,首先選擇其直接相鄰的頂點中長度最短的頂點Vi(注意相鄰和最短),那么當前已知可得從V0到達Vj頂點的最短距離dist[j]=min{dist[j],dist[i]+arcs[i][j]}。

根據這種思路,假設存在G=<V,E>,源頂點為V0,S={V0}, dist[i]記錄V0到Vi的最短距離,path[i]記錄從V0到Vi路徑上的Vi前面的一個頂點。

1.從不在S的V中選擇使dist[i]值最小的頂點i,將i加入到S中;

2.更新與i直接相鄰頂點的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]});(上例是全部更新,不直接相鄰就用“∞”表示)

3.直到S=V。

代碼實現:(代碼來源于網絡)

?

  • #include <iostream>
  • #include<stack>
  • #define M 100
  • #define N 100
  • using namespace std;
  • typedef struct node
  • {
  • int matrix[N][M]; //鄰接矩陣
  • int n; //頂點數
  • int e; //邊數
  • }MGraph;
  • void DijkstraPath(MGraph g,int *dist,int *path,int v0) //v0表示源頂點
  • {
  • int i,j,k;
  • bool *visited=(bool *)malloc(sizeof(bool)*g.n);
  • for(i=0;i<g.n;i++) //初始化
  • {
  • if(g.matrix[v0][i]>0&&i!=v0)
  • {
  • dist[i]=g.matrix[v0][i];
  • path[i]=v0; //path記錄最短路徑上從v0到i的前一個頂點
  • }
  • else
  • {
  • dist[i]=INT_MAX; //若i不與v0直接相鄰,則權值置為無窮大
  • path[i]=-1;
  • }
  • visited[i]=false;
  • path[v0]=v0;
  • dist[v0]=0;
  • }
  • visited[v0]=true;
  • for(i=1;i<g.n;i++) //循環擴展n-1次
  • {
  • int min=INT_MAX;
  • int u;
  • for(j=0;j<g.n;j++) //尋找未被擴展的權值最小的頂點
  • {
  • if(visited[j]==false&&dist[j]<min)
  • {
  • min=dist[j];
  • u=j;
  • }
  • }
  • visited[u]=true;
  • for(k=0;k<g.n;k++) //更新dist數組的值和路徑的值
  • {
  • if(visited[k]==false&&g.matrix[u][k]>0&&min+g.matrix[u][k]<dist[k])
  • {
  • dist[k]=min+g.matrix[u][k];
  • path[k]=u;
  • }
  • }
  • }
  • }
  • void showPath(int *path,int v,int v0) //打印最短路徑上的各個頂點
  • {
  • stack<int> s;
  • int u=v;
  • while(v!=v0)
  • {
  • s.push(v);
  • v=path[v];
  • }
  • s.push(v);
  • while(!s.empty())
  • {
  • cout<<s.top()<<" ";
  • s.pop();
  • }
  • }
  • int main(int argc, char *argv[])
  • {
  • int n,e; //表示輸入的頂點數和邊數
  • while(cin>>n>>e&&e!=0)
  • {
  • int i,j;
  • int s,t,w; //表示存在一條邊s->t,權值為w
  • MGraph g;
  • int v0;
  • int *dist=(int *)malloc(sizeof(int)*n);
  • int *path=(int *)malloc(sizeof(int)*n);
  • for(i=0;i<N;i++)
  • for(j=0;j<M;j++)
  • g.matrix[i][j]=0;
  • g.n=n;
  • g.e=e;
  • for(i=0;i<e;i++)
  • {
  • cin>>s>>t>>w;
  • g.matrix[s][t]=w;
  • }
  • cin>>v0; //輸入源頂點
  • DijkstraPath(g,dist,path,v0);
  • for(i=0;i<n;i++)
  • {
  • if(i!=v0)
  • {
  • showPath(path,i,v0);
  • cout<<dist[i]<<endl;
  • }
  • }
  • }
  • return 0;
  • }
  • ?

  • posted on 2018-07-26 15:37 時空觀察者9號 閱讀(...) 評論(...) 編輯 收藏

    總結

    以上是生活随笔為你收集整理的【转】dijkstra算法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。