單源最短路徑問題

 

 

  • 程序實現
#include <stdio.h>
#define M 65535 //一個無窮大的數,用來表示兩個頂點之間沒有連線時的權值
#define N 5 //頂點數

//Dijkstra算法函數,求給定源點到其餘各頂點的最短路徑
void Dijkstra(int c[N][N], int v, int dist[], int prev[])
{
    int s[N];//當前頂點i是否被選入S集合
    int mindis,dis; 
    int i, j, u;
    //對圖進行賦初值
    for(i=0; i<N; i++)
    {
        dist[i] = c[v][i];//dist[i]表示當前從源到頂點i的最短特殊路徑長度
        s[i] = 0;//當前頂點i沒有被選入S集合
        if(dist[i] == M)//如果當前從源到頂點i的最短特殊路徑長度爲無窮大
            prev[i] = -1;//那麼到達頂點i的最佳路徑上的該頂點的上一個點不是v
        else
            prev[i] = v;//否則,到達頂點i的最佳路徑上的該頂點的上一個點是v
    }
    dist[v] = 0;//源點到源點的距離爲0
    s[v] = 1; //表示源點放入S集合

    //在集合V-S中尋找具有最短路徑的頂點
    for(i=1; i < N; i++)
    {
        mindis = M;
        u = v;
        for (j=0; j < N; j++) 
            if(s[j]==0 && dist[j]<mindis)//判斷j不在S中
            {
                mindis = dist[j];
                u = j;
            }
        s[u] = 1;//找到一個具有最短路徑的頂點,將其放入S集合

        //更新最短路徑
        for(j=0; j < N; j++)
        if(s[j]==0 && c[u][j]<M)//判斷j不在S中並且u到j有一條路徑
        {
            dis = dist[u] + c[u][j];//將路徑更新爲經過S集合中所有頂點的路徑
            // 如果新的路徑更短,就替換掉原來的路徑
            if(dist[j] > dis)
            {
                dist[j] = dis;
                prev[j] = u;
            }
        }
    }
}

// 輸出最短路徑
void PrintPrev(int prev[],int v0,int vn)
{
    int tmp = vn;
    int i, j;
    int tmpprv[N];//臨時存儲路徑
    //初始化數組
    for(i=0; i < N; i++)
        tmpprv[i] = 0;
    //記錄到達點下標
    tmpprv[0] = vn+1;
    //中間點用循環記錄
    for(i =0, j=1; j < N ;j++)
    {
        if(prev[tmp]!=-1 && tmp!=0)
        {
            tmpprv[i] = prev[tmp]+1;
            tmp = prev[tmp];
            i++;
        }
        else break;
    }
    //輸出路徑,數組逆向輸出
    for(i=N-1; i >= 0; i--)
    {
        if(tmpprv[i] != 0)
        { //排除0元素
            printf("V%d", tmpprv[i]);
            if(i) //不是最後一個輸出符號
                printf("->");
        }
    }
    printf("->V%d", vn+1);
}

//主函數
int main()
{
    char *Vertex[N]={"V1", "V2", "V3", "V4", "V5"}; //有向圖的頂點
    int c[N][N]=
    {//有向圖的鄰接矩陣,可以表示出頂點與頂點之間的權值,相當於給圖賦初值
        {0, 10, M, 30, 100},
        {M, 0, 50, M, M},
        {M, M, 0, M, 10},
        {M, M, 20, 0, 60},
        {M, M, M, M, 0},
    };
    int dist[N]; //存放求得的最短特殊路徑長度
    int prev[N];  //存放到達某一頂點的最佳路徑上的該頂點的上一個點
    int i;//用來指代當前頂點,i的範圍從0到有向圖中頂點的個數-1

    //求出源點V1到其餘各點的最短路徑
    Dijkstra(c, 0, dist, prev);
     printf("最短路徑長度爲:\t\t");
     printf("最短路徑爲:");
     printf("\n");
    for(i=0; i < N; i++)
    {
        printf("%s->%s:%d\t\t", Vertex[0], Vertex[i], dist[i]);//輸出最短路徑長度
        PrintPrev(prev, 0, i);//輸出最短路徑
        printf("\n");
    }

    return 0;
}

 

  • 實驗結果與分析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章