算法-图(1)Dijkstra求最短路径

数组dist[],是当前求到的顶点v到顶点j的最短路径长度

数组path[]存放求到的最短路径,如path[4]=2,path[2]=3,path[3]=0,则路径{0,3,2,4}就是0到4的最短路径

数组S[]存放已经求到了最短路径的结点的集合

算法包括两个并行的for循环:

1辅助数组的初始化工作,dist[i]=G.getweight(v,i),时间复杂度为O(n)

2)顶点v是第一个求到了最短路径的结点,dist[v]=0,把它加入数组S[]。

2)进行最短路径求解工作的二重嵌套循环,时间复杂度为O(n^2)。大循环重复n-1次,每次求出一个结点的最短路径长度dist[u]和最短路径path[u]

    进行n次循环,每次从没有加入S[]的顶点中找出最短路径长度dist[i]最小的点,加入集合。

    进行n次循环,每次修改和该点相邻接的结点的最短路径长度dist[j]和最短路径path[j](先判断边是否存在)。

最后总的时间复杂度为O(n^2)。

template <class T,class E>
void ShortestPath(Graph<T,E>& G,T v,E dist[],int path[]){  //求到顶点v的最短路径存储在path[]中,最短距离存储在dist[]中
    //G为带权有向图
    int n=G.NumberOfVertices();
    bool *S=new bool[n];    //数组S存放已经求到了最短路径的结点的集合
    int i,j,k;
    E w,min;
    for (i=0; i<n; i++) {
        dist[i]=G.getWeight(v,i);
        S[i]=false;
        if(i!=v && dist[i]<maxValue) path[i]=v;
        else path[i]=-1;
    }
    S[v]=true;dist[v]=0;  //顶点v加入顶点集合
    for (i=0; i<n-1; i++) {
        min=maxValue;   //每次循环前重置min和u
        int u=v;
        for (j=0; j<n; j++)
            if(S[j]==false && dist[j]<min){ //选不在S中具有最短路径的顶点u
                u=j;
                min=dist[j];
            }
        S[u]=true;  
        for(k=0; k<n; k++){
            w=G.getWeight(u,k);
            if(S[k]==false && w<maxValue && dist[u]+w<dist[k]){
                dist[k]=dist[u]+w;
                path[k]=u;
            }
        }
    }
}

//  从path数组读取最短路径的算法
template <class T,class E>
void printShortestPath(Graph<T,E>& G,int v,E dist[],int path[]){
    cout<<"从顶点"<<G.getValue(v)<<"到其它顶点的最短路径为:"<<endl;
    int i,j,k,n=G.NumberOfVerticles();
    int *d=new int[n];
    for (i=o; i<n; i++)
        if(i!=v){
            j=i;k=0;
            while(j!=v){d[k++]=j;j=path[];}
            cout<<"顶点"<<G.getValue(i)<<"的最短路径为"<<G.getValue(v);
            while(k>0){
                cout<<G.getValue(d[--k])<<"";
                cont<<"最短路径长度为:"<<dist[i]<<endl;
            }
        }
    delete []d;
}
原文地址:https://www.cnblogs.com/yangyuliufeng/p/9287511.html