希望大家能看完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.
最後看一下運行截圖