圖(四)之Adjecancy Matrix的Floyd算法

上一篇關於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

運行結果如下圖:


大家可以去我的github clone一下代碼:

https://github.com/cremyos/Graph_Floyd/

這個代碼無法打印詳細的路徑,因爲在84行處的

(Path+j)[k][l] = (Path+j)[i][l]||(Path+i)[k][l];

應該是把路徑拼接起來,結果採用的是或運算,所以出問題了,具體怎麼改。。。還沒想到什麼好的辦法!

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