最短路径之Floyd-Warshell算法

同Bellman-Ford算法一样,Floyd Warshell算法同业可以处理带有负权(但不含负权回路)的图的最短了路径问题。不过该算法并不是单源路径算法,它运行一次计算的是所有两个顶点间的最短路径,时间复杂度为Theta(n^3)。通过改进,可以打印所有路径(一般保存路径会增加空间复杂度)。打印的算法通过保存任意两个节点之间通过的index为最大值的节点。


开始吧,floyd算法。

/*
 * szl_floyd_warshell.h
 */
#ifndef SZL_FLOYD_WARSHELL_H
#define SZL_FLOYD_WARSHELL_H


void szl_floyd_warshell(int* graph[], int n);
#endif

/*
 * szl_floyd_warshell.c
 */
#include "szl_floyd_warshell.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


void szl_floyd_warshell(int* graph[], int n);
static void print_one_path(int *dist[], int *next[], int i, int j);




int main( int argc ,char ** argv){
int **graph;
int i,j;
int u,v,w;
/*
* the number of nodes and vertices
*/
int n,m;


/*
* read from a file in the current directory named 'data.txt'
*/
FILE* data_file;

if( 1 == argc){
data_file=fopen("data.txt", "r");
}
else{
data_file=fopen(argv[1], "r");
}
assert(NULL!=data_file);


//printf("input vertices and edges.\n");
fscanf(data_file,"%d%d",&n,&m);

/*
* implement a graph with matrix
*/
graph=(int **)malloc(sizeof(int *) * n);
assert(NULL != graph);
for(i=0;i<n;i++){
graph[i]=(int *)malloc(sizeof(int)*n);
assert(NULL!=graph[i]);
}

/*
* initialization the weight of the graph with a value which means this edge is not exists.
*/
for(i=0;i<n;i++){
for(j=0;j<n;j++){
graph[i][j]=INT_MAX;
}
}


/*
* input the edge and its weight
*/
for(i=0;i<m;i++){
fscanf(data_file,"%d%d%d",&u,&v,&w);
graph[u][v]=w;
}


/*
* call the dijkstra to address it
*/
szl_floyd_warshell(graph, n);


/*
* close the input stream and free the memory allocated manually.
*/
fclose(data_file);
for(i=0;i<n;i++){
free(graph[i]);
}
free(graph);


return 0;
}


void szl_floyd_warshell(int* graph[], int n){
int **dist;
int **next;


int i,j,k;
/*
* memory allocated
*/
dist = (int **)malloc(sizeof(int *)*n);
next = (int **)malloc(sizeof(int *)*n);
for(k=0;k<n;k++){
dist[k] = (int *)malloc(sizeof(int)*n);
next[k] = (int *)malloc(sizeof(int)*n);
}


/*
* initialization 1
*/
for(i=0;i<n;i++){
for(j=0;j<n;j++){
next[i][j] = -1; //Undefined
dist[i][j] = INT_MAX; // this statement is optional
}
}
/*
* initialization 2
* for each vertex, the shortest path is zero
*/
for(k=0;k<n;k++){
dist[k][k] = 0; // this is optional
}
/*
* initialization 3
* for each edge (u,v), the distance from  u to v is  initialized as the weight of edge (u,v)
*/
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(graph[i][j] != INT_MAX){
dist[i][j] = graph[i][j];
}
}
}


for(k=0;k<n;k++){
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(dist[i][k] < INT_MAX && dist[k][j] < INT_MAX){
if(dist[i][j] == INT_MAX){
next[i][j] = k;
dist[i][j] = dist[i][k] + dist[k][j];
}
else{
if(dist[i][j] > dist[i][k]+dist[k][j]){
next[i][j] = k;
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}
}
/*
* paths
*/
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(i!=j){
printf("[%d][%d]",i,j);
if(dist[i][j] == INT_MAX){
printf(": 没有路径.");
}
else{
printf(", 距离为: %d.",dist[i][j]);
printf("\n");
if(next[i][j] == -1){
printf("        这是一条边.");
}
else{
printf("        途径节点:");
print_one_path(dist, next, i, j);
}
}
printf("\n");
}
}
}

for(k=0;k<n;k++){
free(dist[k]);
free(next[k]);
}
free(dist);
free(next);
}


static void print_one_path(int *dist[], int *next[], int i, int j){
int immediate;
if(dist[i][j] == INT_MAX){
printf("no path.");
return;
}
immediate = next[i][j];
if(-1 == immediate){
return;
}
else{
print_one_path(dist,next,i,immediate);
printf("[%d]",immediate);
print_one_path(dist,next,immediate,j);
}

}

4 5
0 2 -2
1 0 4
1 2 3
2 3 2
3 1 -1
0 3


也就是wiki的这张图:

运行结果:

另一个测试数据:

9 16
0 1 9
0 2 7
0 3 4
1 4 -4
2 3 -4
2 5 3
3 1 5
3 4 3
3 6 2
4 6 -2
4 8 -3
5 3 -8
5 7 -3
6 7 5
6 8 2
7 8 -7
0 8


http://blog.csdn.net/qianlizhima1/article/details/8693484原网址



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值