弗洛伊德算法Floyd个人看法(凭个人理解进行纠错)以及Floyd完整代码

该问题,也是一个错误吧,发现也是在学习Floyd的动手实现过程中。我参考学习数据结构与算法书,自己也是动手敲了敲Floyd算法的代码,发现结果和正确的答案是不同的,就是说一些点是过不了的,是错误的。然后也是在网站上搜索Floyd算法,发现博主的和书上的没有什么不同,但测试出来就是不对。有bug就一定有原因,单步运行,一步一步找问题所在,最后在更新距离处发现了问题根源,不能单单只写 path[i][j] = k;  必须写完整,必须考虑 path[k][j] != j 这种情况。一些博主,很多数据结构书在此处只写了   path[i][j]=k;    这是错误的!大家可以去动手尝试一下,才能真正理解。越来越认可动手实现是最重要的也是最基本的!

完整Floyd代码及注释如下,多看看代码,尤其是if else:

最后附有该代码所对应的图,方便大家更好理解。

#include<iostream>
using namespace std;
typedef struct
{
	char vexs[7];        //顶点值
	int edges[7][7];   //邻接矩阵
	int vnum, enum1; //顶点数和边数
}MGraph;
void CreateMGraph(MGraph*);
void floyd(MGraph* );
int main()
{
	MGraph G;
	CreateMGraph(&G);
	floyd(&G);
}
void CreateMGraph(MGraph* G)
{
	G->vnum = 7;  G->enum1 = 7;
	char c = 'A';
	for (int i = 0; i < G->vnum; i++, c++)
		G->vexs[i] = c;
	for (int i = 0; i < G->vnum; i++)
		for (int j = 0; j < G->vnum; j++)
			G->edges[i][j] = 1000;                   //因为1000对于该程序已经足够大,认为无穷大
	if (1)
	{
		G->edges[0][2] = 10;                     //也可以每次运行时再输入  不过麻烦
		G->edges[1][2] = 7;
		G->edges[1][6] = 9;
		G->edges[1][3] = 5;
		G->edges[2][0] = 10;
		G->edges[2][1] = 7;
		G->edges[3][1] = 5;
		G->edges[3][5] = 2;
		G->edges[4][5] = 6;
		G->edges[5][4] = 6;
		G->edges[5][3] = 2;
		G->edges[5][6] = 3;
		G->edges[6][1] = 9;
		G->edges[6][5] = 3;
	}
}
void floyd(MGraph* G)
{
	int path[7][7], dist[7][7];                        //path[i][j]是指i到j的路径中相对于j的前驱     dist[i][j]是i到j的最短路径距离
	for (int i = 0; i < G->vnum; i++)
		for (int j = 0; j < G->vnum; j++)
		{
			dist[i][j] = G->edges[i][j]; 
			path[i][j] = j;                                  //暂时默认path[i][j] j的前驱为j
		}
	for (int k = 0; k < G->vnum; k++)      //注意三层for循环
		for (int i = 0; i < G->vnum; i++)
			for (int j = 0; j < G->vnum; j++)
				if (dist[i][j] > (dist[i][k] + dist[k][j]))      
				{                                                                  //更新距离
					dist[i][j] = dist[i][k] + dist[k][j];          
					if(path[k][j] != j)                                    //if else是重点!!!读者细细体会
						path[i][j] = path[k][j];
					else
					path[i][j] = k;                                       
					//很多博主,很多数据结构书在此处只写了   path[i][j]=k;    这是错误的!!!必须考虑 path[k][j] != j 这种情况
				}
	for (int i = 0; i < G->vnum; i++)
		for (int j = 0; j < G->vnum; j++)
			if (i != j)                                                         //直接忽略自身点到自身
			{
				printf("%c到%c的最短路径长度:%d\n", i + 17 + '0', j + 17 + '0', dist[i][j]);
				printf("路径为:%c", i + 17 + '0');
				if (path[i][j] == j)
					printf("-->%c\n", j + 17 + '0');
				else
				{
					int k = j, arry[7] = { 0 }, a = 0;          //使用一个arry数组来逆序输出路径,保证路径的顺序正确
					while (path[i][k] != k)
					{
						k = path[i][k];
						arry[a] = k;
						a++;
					}
					for (k = a - 1; k >= 0; k--)                             //注意逆序输出
						printf("-->%c", arry[k] + 17 + '0');
					printf("-->%c\n", j + 17 + '0');
				}
			}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值