@[TOC]弗洛伊德(Floyd)算法
弗洛伊德(Floyd)算法示例、输出最短路径方式、负值环问题
弗洛伊德(Floyd)算法:在大话数据结构和浙大数据结构教材中的程序稍有不同,主要是在显示各顶点间的最短路径的方式,记录一下。
数据图:
代码
数组P(参考大话数据结构)、数组pf(参考浙大教材)用于记录最短路径,显示方式上:浙大教材需要用到递归程序.
负值环:Floyd算法允许负值边,不允许负值环。但下面的示例程序并不允许负值边的存在,因为例程是用无向有权图的邻接矩阵,负值边会被程序理解为两条方向相反的有向边,从而组成负值环
问题:刚开始,我把数组 pf 设置为在main中的局部变量,结果在递归程序lujing
中出错,显示“Program received signal SIGSEGV”,后来改成全局变量就正常了,不知道为啥,望大佬解答一下,谢谢
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#include<stdbool.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXEDGE 20
#define MAXVEX 20
#define GRAPH_INFINITY 65535
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef struct
{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}MGraph;
typedef int Patharc[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];
Patharc pf;
/* 构件图 */
void CreateMGraph(MGraph *G)
{
int i, j;
/* printf("请输入边数和顶点数:"); */
G->numEdges=16;
G->numVertexes=9;
for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
{
G->vexs[i]=i;
}
for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
{
for ( j = 0; j < G->numVertexes; j++)
{
if (i==j)
G->arc[i][j]=0;
else
G->arc[i][j] = G->arc[j][i] = GRAPH_INFINITY;
}
}
G->arc[0][1]=1;
G->arc[0][2]=5;
G->arc[1][2]=3;
G->arc[1][3]=7;
G->arc[1][4]=5;
G->arc[2][4]=1;
G->arc[2][5]=7;
G->arc[3][4]=2;
G->arc[3][6]=3;
G->arc[4][5]=3;
G->arc[4][6]=6;
G->arc[4][7]=9;
G->arc[5][7]=5;
G->arc[6][7]=2;
G->arc[6][8]=7;
G->arc[7][8]=4;
for(i = 0; i < G->numVertexes; i++)
{
for(j = i; j < G->numVertexes; j++)
{
G->arc[j][i] =G->arc[i][j];
}
}
}
/* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */
bool ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D)
{
int v,w,k;
for(v=0; v<G.numVertexes; ++v) /* 初始化D与P */
{
for(w=0; w<G.numVertexes; ++w)
{
(*D)[v][w]=G.arc[v][w]; /* D[v][w]值即为对应点间的权值 */
(*P)[v][w]=w;
pf[v][w]=-1; /* 初始化P */
}
}
for(k=0; k<G.numVertexes; ++k)
{
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w])
{/* 如果经过下标为k顶点路径比原两点间路径更短 */
(*D)[v][w]=(*D)[v][k]+(*D)[k][w];/* 将当前两点间权值设为更小的一个 */
(*P)[v][w]=(*P)[v][k];//(*P)[v][k];/* 路径设置为经过下标为k的顶点 */
pf[v][w]=k;
if(v==w && (*D)[v][w]<0) //若发现负值圈
return false; //不能正确解决,返回错误标记
}
}
}
}
return true;
}
void lujing(int a, int b) {
int abc = pf[a][b];
if (abc==-1) return;
else {
lujing(a,abc);
printf(" -> %d",abc);
lujing(abc,b);
}
}
int main(void)
{
int v,w,k;
MGraph G;
Patharc P;
ShortPathTable D; //* 求某点到其余各点的最短路径
CreateMGraph(&G);
ShortestPath_Floyd(G,&P,&D);
printf("最短路径D\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
printf("%d\t",D[v][w]);
}
printf("\n");
}
printf("最短路径P(参考大话数据结构)\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
printf("%d ",P[v][w]);
}
printf("\n");
}
printf("各顶点间最短路径如下(参考大话数据结构):\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=v+1; w<G.numVertexes; w++)
{
printf("v%d-v%d weight: %d ",v,w,D[v][w]);
k=P[v][w]; //* 获得第一个路径顶点下标
printf(" path: %d",v); //* 打印源点
while(k!=w) //* 如果路径顶点下标不是终点
{
printf(" -> %d",k); //* 打印路径顶点
k=P[k][w]; //* 获得下一个路径顶点下标
}
printf(" -> %d\n",w); //* 打印终点
}
printf("\n");
}
printf("最短路径pf(参考浙大教材,pf为全局变量,否则在递归中容易内存出错)\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
printf("%d\t",pf[v][w]);
}
printf("\n");
}
printf("各顶点间最短路径如下(参考浙大教材,递归方式):\n");
for(v=0; v<G.numVertexes; ++v) {
for(w=v+1; w<G.numVertexes; w++) {
printf("v%d-v%d : ",v,w);
printf(" path: %d",v); //* 打印开始点
lujing(v,w);
printf(" -> %d#\n",w); //* 打印终止点
}
printf("\n");
}
return 0;
}