1. 程式人生 > >迪傑斯特拉演算法(可列印最短路徑)(資料結構題集C語言版7.11)

迪傑斯特拉演算法(可列印最短路徑)(資料結構題集C語言版7.11)

轉自 https://blog.csdn.net/cxllyg/article/details/7604812

 

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

#define INFINITY 65535//無邊時的權值
#define MAX_VERTEX_NUM 10//最大頂點數

typedef struct MGraph{
    string vexs[10];//頂點資訊
    int arcs[10][10];//鄰接矩陣
    int vexnum, arcnum;//頂點數和邊數
}MGraph;

int LocateVex(MGraph G, string u)//返回頂點u在圖中的位置
{
    for(int i=0; i<G.vexnum; i++)
        if(G.vexs[i]==u)
            return i;
    return -1;
}

void CreateDN(MGraph &G)//構造有向網
{
    string v1, v2;
    int w;
    int i, j, k;
    cout<<"請輸入頂點數和邊數:";
    cin>>G.vexnum>>G.arcnum;

    cout<<"請輸入頂點:";
    for(i=0; i<G.vexnum; i++)
        cin>>G.vexs[i];

    for(i=0; i<G.vexnum; i++)
        for(j=0; j<G.vexnum; j++)
            G.arcs[i][j]=INFINITY;

    cout<<"請輸入邊和權值:"<<endl;
    for(k=0; k<G.arcnum; k++)
    {
        cin>>v1>>v2>>w;
        i=LocateVex(G, v1);
        j=LocateVex(G, v2);
        G.arcs[i][j]=w;
    }
}

//迪傑斯特拉演算法求有向網G的v0頂點到其餘頂點v的最短路徑p[v]及帶權長度D[v]
//p[][]=-1表示沒有路徑,p[v][i]存的是從v0到v當前求得的最短路徑經過的第i+1個頂點(這是列印最短路徑的關鍵),則v0到v的最短路徑即為p[v][0]到p[v][j]直到p[v][j]=-1,路徑列印完畢。
//final[v]為true當且僅當v∈S,即已經求得從v0到v的最短路徑。
void ShortestPath_DIJ(MGraph G, int v0, int p[][MAX_VERTEX_NUM], int D[])
{
    int v, w, i, j, min;
    bool final[10];

    for(v=0; v<G.vexnum; v++)
    {
        final[v]=false;//設初值
        D[v]=G.arcs[v0][v];//D[]存放v0到v得最短距離,初值為v0到v的直接距離
        for(w=0; w<G.vexnum; w++)
            p[v][w]=-1;//設p[][]初值為-1,即沒有路徑
        if(D[v]<INFINITY)//v0到v有直接路徑
        {
            p[v][0]=v0;//v0到v最短路徑經過的第一個頂點
            p[v][1]=v;//v0到v最短路徑經過的第二個頂點
        }
    }

    D[v0]=0;//v0到v0距離為0
    final[v0]=true;//v0頂點併入S集

    for(i=1; i<G.vexnum; i++)//其餘G.vexnum-1個頂點
    {//開始主迴圈,每次求得v0到某個頂點v的最短路徑,並將v併入S集,然後更新p和D
        min=INFINITY;
        for(w=0; w<G.vexnum; w++)//對所有頂點檢查
            if(!final[w] && D[w]<min)//在S集之外(即final[]=false)的頂點中找離v0最近的頂點,將其賦給v,距離賦給min
            {
                v=w;
                min=D[w];
            }
        final[v]=true;//v併入S集
        for(w=0; w<G.vexnum; w++)//根據新併入的頂點,更新不在S集的頂點到v0的距離和路徑陣列
        {
            if(!final[w] && min<INFINITY && G.arcs[v][w]<INFINITY && (min+G.arcs[v][w]<D[w]))
            {//w不屬於S集且v0->v->w的距離<目前v0->w的距離
                D[w]=min+G.arcs[v][w];//更新D[w]
                for(j=0; j<G.vexnum; j++)//修改p[w],v0到w經過的頂點包括v0到v經過的所有頂點再加上頂點w
                {
                    p[w][j]=p[v][j];
                    if(p[w][j]==-1)//在p[w][]第一個等於-1的地方加上頂點w
                    {
                        p[w][j]=w;
                        break;
                    }
                }

            }
        }
    }
}

int main()
{
    int i, j;
    MGraph g;
    CreateDN(g);
    int p[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//最短路徑陣列p
    int D[MAX_VERTEX_NUM];//最短距離陣列D
    ShortestPath_DIJ(g, 0, p, D);

    cout<<"最短路徑陣列p[i][j]如下:"<<endl;
    for(i=0; i<g.vexnum; i++)
    {
        for(j=0; j<g.vexnum; j++)
            cout<<setw(3)<<p[i][j]<<" ";
        cout<<endl;
    }

    cout<<g.vexs[0]<<"到各頂點的最短路徑及長度為:"<<endl;
    for(i=0; i<g.vexnum; i++)
    {
        if(i!=0 && D[i]!=INFINITY)
        {
            cout<<g.vexs[0]<<"-"<<g.vexs[i]<<"的最短路徑長度為:"<<D[i];
            cout<<"  最短路徑為:";
            for(j=0; j<g.vexnum; j++)
            {
                if(p[i][j]>-1)
                    cout<<g.vexs[p[i][j]]<<" ";
            }
            cout<<endl;
        }
        else if(D[i]==INFINITY)
            cout<<g.vexs[0]<<"-"<<g.vexs[i]<<":"<<"不可達"<<endl;
    }
return 0;
}