dijkstra算法求最短路徑

希望大家能看完prim算法後再來看這個算法,因爲兩者思路差不多。
先來看一下自定義的結構體

typedef char VexType;
typedef int AdjType;
typedef struct{
    int n;
    VexType vexs[MaxNode];//保存節點
    AdjType arcs[MaxNode][MaxNode];//從矩陣獲得節點與節點間的距離
}GraphMatrix;
typedef struct{
    AdjType length;//邊長
    int prevex;//先驅節點
}path;

主程序

void main()
{
    GraphMatrix *mygraph;
    path *mydist;
//  Edge *mymst;
    mygraph = (GraphMatrix*)malloc(sizeof(GraphMatrix));
    //mymst = (Edge*)malloc(sizeof(Edge));
    mydist = (path*)malloc(sizeof(path));
    CreateGraph(mygraph,6);
    printf("testing creategraph\n");
    dijkstra(mygraph,mydist);
    printf("testing dijkstra:\n");
    print_path(mygraph,mydist);

}

creategraph函數是從txt裏讀取矩陣的函數,我寫在了prim算法的帖子裏,大家可以去看一下,這裏就不說了。
來看一下dikstra算法

void dijkstra(GraphMatrix *graph,path *dist)
{
    int i,j,min;
    AdjType minw;
    dist[0].length = 0;
    dist[0].prevex = 0;
    graph->arcs[0][0] = 1;//表示v0加入集合
    for(i=1;i<graph->n;i++)//從V1節點開始
    {
        dist[i].length = graph->arcs[0][i];//初始化v0到各個節點的距離
        if(dist[i].length!=Max)
        {
            dist[i].prevex = 0;//不等於Max說明V0可以到Vi節點
        }
        else
        {
            dist[i].prevex = -1;//V0到Vi沒有路徑
        }
    }
    for(i=1;i<graph->n;i++)//一次循環就會找到V0到其中一個頂點的最短距離,所以循環節點數-1次
    {
        minw = Max;
        min = 0;
        for(j=1;j<graph->n;j++)
        {
            if((graph->arcs[j][j]==0)&&(dist[j].length<minw))//==0說明節點j還未加入
            {
                minw = dist[j].length;
                min = j;
            }
        }
        if(min==0)//如果都不等於0,說明所有節點都已加入,也就是已經調整好了,如果都大於minw說明所有路徑已經達到最短
        {
            break;
        }
        graph->arcs[min][min]=1;//將頂點爲min的頂點加入集合,此時V0到Vmin的節點的最短距離已經找到,下面進行調整時就是判斷通過Vmin點再到其他點距離是否會減少
        for(j=1;j<graph->n;j++)
        {
            if(graph->arcs[j][j]==1)
            {
                continue;//V0到節點Vi的最短路徑已經找到,不在進行調整
            }
            if(dist[j].length>dist[min].length+graph->arcs[min][j])//V0到Vmin的距離+Vmin到Vj的距離
            {
                dist[j].length = dist[min].length+graph->arcs[min][j];//變更路徑長度
                dist[j].prevex = min;//V0到Vj的先驅節點從V0變更成Vmin
            }
        }
    }
}

dist數組的元素是V0節點到其他各點的路徑。如果二維數組的graph->arcs[i][i]的值爲0,說明此時Vi節點還沒加入我們的判斷範圍,就是說我們求得最短路徑裏不能經過Vi節點,所以我們一開始默認V0節點加入判斷範圍,也就是說,我們求得路徑就是V0節點到其他節點的最短路徑,所以for循環是從1開始的。以爲不用求V0到V0的最短路徑
先初始化V0到其他各節點的距離,這些距離是從txt裏存儲的矩陣中讀取的。如果兩個節點之間沒有路徑,就默認路徑距離爲1000.路徑前驅節點爲-1.
1.初始化完成後,進行fo循環來尋找最短路徑。先找一條最短路徑(當前數組元素裏length最小的).if((graph->arcs[j][j]==0)&&(dist[j].length

void print_path(GraphMatrix* graph, path* dist)
{
    int i,j;
    for(i=1;i<graph->n;i++)
    {
        j = i;
        if(dist[i].length==Max)
        {
            printf("V0到V%d沒有路徑\n",i);//設定牀爲MAX說明沒有路徑
        }
        else
        {
            printf("V%d到V0的路徑爲:  %d ",i,i);
            while(dist[j].prevex!=0)//Vj的前驅節點不是V0說明經過其他節點Vx,V0到Vx的路徑中的前驅節點爲dist[j].prevex,循環驗證
            {
                printf("%d ",dist[j].prevex);
                j = dist[j].prevex;
            }
            printf("0");
            printf("\nV%d到V0的路徑長度爲%d\n",i,dist[i].length);
            printf("\n\n");
        }
    }
}

這裏其實就是把數組元素的一些成員打印出來。數組下標i就代表V0到Vi的最短路徑.
需要說明兩點.
1.上面已經提到了,如果路徑長度等於MAX(1000)。說明兩個節點之間沒有路徑。
2.我們找的最短路徑是V0到其他節點的最短路徑。如果第i條路徑的前驅節點不是V0,假設爲Vj,說明V0到這個節點的最短路徑是經過其他節點的。這個時候我們還要找第J條路徑,就這樣往前找,知道前驅節點爲V0.
最後看一下運行截圖
這裏寫圖片描述

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