欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Dijkstra算法

程序员文章站 2022-04-06 18:46:13
...

我们用一个例子来具体说明Dijkstra算法的流程。
Dijkstra算法
定义源点为0,dist[i]为源点0到顶点i的最短路径。其过程描述如下:

步骤 dist[1] dist[2] dist[3] dist[4] 已找到的集合
第1步 8 1 2 +∞ { 2 }
第2步 8 × 2 4 { 2, 3 }
第3步 5 × × 4 { 2, 3, 4 }
第4步 5 × × × { 2, 3, 4, 1 }
第5步 × × × × { 2, 3, 4, 1 }
第1步:从源点0开始,找到与其邻接的点:1,2,3,更新dist[]数组,因0不与4邻接,故dist[4]为正无穷。在dist[]中找到最小值,其顶点为2,即此时已找到0到2的最短路。

第2步:从2开始,继续更新dist[]数组:2与1不邻接,不更新;2与3邻接,因0→2→3比dist[3]大,故不更新dist[3] ;2与4邻接,因0→2→4比dist[4]小,故更新dist[4]为4。在dist[]中找到最小值,其顶点为3,即此时又找到0到3的最短路。

第3步:从3开始,继续更新dist[]数组:3与1邻接,因0→3→1比dist[1]小,更新dist[1]为5;3与4邻接,因0→3→4比dist[4]大,故不更新。在dist[]中找到最小值,其顶点为4,即此时又找到0到4的最短路。

第4步:从4开始,继续更新dist[]数组:4与1不邻接,不更新。在dist[]中找到最小值,其顶点为1,即此时又找到0到1的最短路。

第5步:所有点都已找到,停止。

对于上述步骤,你可能存在以下的疑问:
Dijkstra算法
若A作为源点,与其邻接的只有B,C,D三点,其dist[]最小时顶点为C,即就可以确定A→C为A到C的最短路。但是我们存在疑问的是:是否还存在另一条路径使A到C的距离更小? 用反证法证明。

假设存在如上图的红色虚线路径,使A→D→C的距离更小,那么A→D作为A→D→C的子路径,其距离也比A→C小,这与前面所述“dist[]最小时顶点为C”矛盾,故假设不成立。因此这个疑问不存在。

根据上面的证明,我们可以推断出,Dijkstra每次循环都可以确定一个顶点的最短路径,故程序需要循环n-1次。

#include<iostream>
#include<sstream>
using namespace std;
const int Max=100;
string Int_to_String(int n)//int转换string 
{
ostringstream stream;
stream<<n; //n为int类型
return stream.str();
}
class MGraph{
    public:
        MGraph(){

        }
        MGraph(int n,int e);
        ~MGraph(){

        }
    public:
    int vertex[Max];
    int arc[Max][Max];
    int vertexNum,arcNum;
};
MGraph::MGraph(int n,int e){
    int i,j;
    vertexNum=n;
    arcNum=e;
    for(int i=0;i<vertexNum;i++)
    vertex[i]=i;
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    arc[i][j]=10000;
    cout<<"请输入图中各边的情况:"<<endl;
    for(int k=0;k<e;k++){
        cin>>i>>j;
        cin>>arc[i][j];
    }
}
void Dijkstra(MGraph G,int v){
    int dist[Max],s[Max];
    string path[Max]; 
    for(int i=0;i<G.vertexNum;i++)
    {
    dist[i]=G.arc[v][i];
    if(dist[i]!=10000)
    path[i]=Int_to_String(G.vertex[v])+"->"+Int_to_String(G.vertex[i]);
    else
    path[i]="";
    }
    s[0]=v;
    dist[v]=0;
    int num=1;
    for(int i=0;i<G.vertexNum;i++)
    {
    int t=10000,k;
    for(int j=0;j<G.vertexNum;j++)
    {
        if(dist[j]<t&&dist[j]!=0)
        {
        t=dist[j];
        k=j;
        }
    }
    cout<<"终点为:"<<k<<"  最短路径长度为:"<<dist[k]<<"  过程:"<<path[k]<<endl;
    s[num++]=k;
    for(int j=0;j<G.vertexNum;j++){
        if(dist[j]!=0&&dist[j]>(dist[k]+G.arc[k][j])){
            dist[j]=dist[k]+G.arc[k][j];
            path[j]=path[k]+"->"+Int_to_String(j);
        }
    }
    dist[k]=0;
    if(num==G.vertexNum)
    break;
    }
    cout<<"找到终点的顺序为:"<<endl;
    for(int i=1;i<num;i++)
    cout<<s[i]<<" "; 
    cout<<endl;
}
int main(){
   int n,e,v;
   cout<<"输入起点下标:"<<endl; 
   cin>>v;
   cout<<"输入图的顶点数和边数:"<<endl;
   cin>>n>>e;
   MGraph G(n,e);
   Dijkstra(G,v);
   return 0;
}

Dijkstra算法
代码如有错误,欢迎大家指点出来!