同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原网址