上一篇關於Dijkstra算法的實現發現一個問題,就是Dijkstra算法主要針對的是一個頂點到其他頂點間的最小距離,那麼問題來了,如何實現每一對頂點間的最小距離,是選擇Dijkstra算法進行n次遍歷?顯然發現會很麻煩,對於n次遍歷的Dijkstra算法,時間複雜度爲O(n^3)。這裏介紹的Floyd算法時間複雜度算然和前者相同,但是至少實現的形式上能簡單一些!
Floyd算法基本思想是:
假設求從頂點vi到vj的最短路徑。如果從vi到vj有弧,則從vi到vj存在一條長度爲arc[i][j]的路徑,該路徑不一定是最短路徑,尚需進行n次試探。首先考慮路徑(vi,vj)和(vi,v0,vj)是否存在(即判別弧(vi,v0)和(v0,vj)是否存在)。如果存在,則比較(vi,vj)和(vi,v0,vj)的路徑長度取長度較短者爲從vi到vj的中間頂點的序號不大於0的最短路徑。假設在路徑上在增加一個頂點v1,也就是說,如果(vi,...,v1)和(v1,.....,vj)分別是當前找到的中間頂點的序號不大於0的最短路徑,那麼(vi,...,v1,...vj)就用可能是從vi到vj的中間點點序號不大於1的最短路徑。講他和已經得到的從vi到vj中間頂點序號不大於0的最短路徑比較,從中選出中間頂點的序號不大於1 的最短路徑之後在增加一個頂點v2,繼續進行試探。此時我們需要藉助三階矩陣來實現這個過程的存儲。
下面把算法僞代碼貼出來:
給出書中的測試用例圖:
還有建立的輔助矩陣:
下面分享代碼:
/*
************************************************
*Name : Matrix_Floyd.c *
*Date : 2015-06-17 *
*Author : sniper *
*Aim : Floyd algrithm to get the shortest route*
* each node to others in the graph *
************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MATRIX_NUMBER 100
#define INF 32768
int main()
{
int i,j,k,l;
int node_count,edge_count;
int node_pair1,node_pair2,weight;
int Distance[MAX_MATRIX_NUMBER][MAX_MATRIX_NUMBER];
int edge[MAX_MATRIX_NUMBER][MAX_MATRIX_NUMBER];
int Path[MAX_MATRIX_NUMBER][MAX_MATRIX_NUMBER];
node_count=edge_count=node_pair1=node_pair2=weight=0;
printf("please input the number of node and edge: ");
scanf("%d %d",&node_count,&edge_count);
memset(Distance,0,sizeof(Distance));
memset(edge,0,sizeof(edge));
memset(Path,0,sizeof(Path));
/*
*Create the graph
*/
for(i=0;i<edge_count;i++)
{
printf("please input the node pair: ");
/*
*node_pair1 node_pair2 two side of edge and
*the weight means the weight of edge
*/
scanf("%d %d %d",&node_pair1,&node_pair2,&weight);
edge[node_pair1][node_pair2] = weight;
}
printf("after create the graph is :\n");
for(i=0;i<node_count;i++)
{
for(j=0;j<node_count;j++)
{
if(i!=j && edge[i][j]==0)
edge[i][j]=INF;
printf(" %d ",edge[i][j]);
}
printf("\n");
}
/*
*Floyd
*/
for(i=0;i<node_count;i++)
{
for(j=0;j<node_count;j++)
{
Distance[i][j]=edge[i][j];
printf(" %d ",Distance[i][j]);
for(k=0;k<node_count;k++)
if(Distance[i][j]>0)
{
(Path+i)[j][i]=1;
(Path+i)[j][j]=1;
}
}
printf("\n");
}
printf("+++++++++++++++++++++++++++++++++\n");
for(i=0;i<node_count;i++)
for(j=0;j<node_count;j++)
for(k=0;k<node_count;k++)
if(Distance[j][i]+Distance[i][k]<Distance[j][k])
{
Distance[j][k]=Distance[j][i]+Distance[i][k];
for(l=0;l<node_count;l++)
(Path+j)[k][l] = (Path+j)[i][l]||(Path+i)[k][l];
}
for(i=0;i<node_count;i++)
{
for(j=0;j<node_count;j++)
{
if(Distance [i][j]!=0)
{
printf("%c -> %c = %d \n",i+'A',j+'A',Distance[i][j]);
}
}
}
return 0;
}
當然了還有測試用例:
3 5
0 1 4
0 2 11
1 0 6
1 2 2
2 0 3
運行結果如下圖:
https://github.com/cremyos/Graph_Floyd/
這個代碼無法打印詳細的路徑,因爲在84行處的
(Path+j)[k][l] = (Path+j)[i][l]||(Path+i)[k][l];
應該是把路徑拼接起來,結果採用的是或運算,所以出問題了,具體怎麼改。。。還沒想到什麼好的辦法!