用C语言实现传递闭包(warshall算法)

目录

1.传递闭包的概念

2.warshall算法求传递闭包步骤

3.C语言实现


1.传递闭包的概念

通俗的说就是,当我们定义了一个关系R是传递的,一切满足这个R的结果集合

例如:我有一个具有传递性的R集合{(1,2),(1,3),(2,4),(4,1),(2,3)},假设这个传递关系是X,1与2有X,2与4有X,那1与4有X,依次把所有的关系找出来,结果就是R的传递闭包{(1,1),(1,2),(1,3),(1,4),(2,1),(2,3),(2,4),(4,1),(4,2),(4,3),(4,4)}

2.warshall算法求传递闭包步骤

设我们要求A这个n阶方阵的传递闭包

数学公式:R(传递闭包)=A(一阶矩阵)+A^2(二阶)+A^3(三阶)+…+A^n(n阶)

(注意,这里的+是逻辑运算中的析取运算)

1.设矩阵 A=R;

2.设i=1;

3.对所有j(1,2,3...,n),如果A[j,i]=1,那么对于k=1,2,...,n。A[j,k]+A[i,k]=A[j,k];

4.i加1;

5.i<=n,循环3)的步骤;不满足则结束。

3.C语言实现

用4*4的数组举例吧

#include <stdio.h>
#define ROW 4
#define COL 4

void warshall(int arr[ROW][COL], int row, int col)    //warshall算法函数实现
{
	int i = 0;
	int j = 0;
	int k = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (arr[j][i] == 1)
			{
				for (k = 0; k < col; k++)
				{
					arr[j][k] = (arr[j][k] || arr[i][k]);
				}
			}
		}
	}
}

void print(int arr[ROW][COL], int row, int col)    //用表的形式呈现数组的函数
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	int arr[ROW][COL] = { {0,1,0,1},{0,1,1,0},{0,0,0,0},{1,0,1,1} };   //1.定义一个4*4数组
	print(arr, 4, 4);   //2.用表的形式呈现之前的数组的函数
	printf("\n");   //3.分一下行,跟后面要呈现的数组分开
	warshall(arr, 4, 4);   //4.warshall算法函数实现
	print(arr, 4, 4);   //5.打印实现算法后的数组
	return 0;
}

最后的结果演示:

### 回答1: Warshall算法是一种求解传递闭包算法,其基本思想是利用矩阵乘法的性质,通过多次迭代来逐步构建传递闭包。 具体实现过程如下: 1. 初始化传递闭包矩阵,即将原始矩阵复制到传递闭包矩阵中。 2. 对传递闭包矩阵进行多次迭代,每次迭代都将传递闭包矩阵中的每个元素与其所在行和列的所有元素进行逻辑“或”操作,得到新的传递闭包矩阵。 3. 当传递闭包矩阵不再发生变化时,迭代结束,此时得到的传递闭包矩阵即为原始矩阵的传递闭包。 需要注意的是,传递闭包矩阵的元素类型应为布尔型,表示两个节点之间是否存在路径。 在C语言中,可以使用二维数组来表示矩阵,使用循环嵌套来进行迭代操作,具体实现代码如下: void warshall(int n, int graph[][n]) { int i, j, k; for (k = 0; k < n; k++) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { graph[i][j] = graph[i][j] || (graph[i][k] && graph[k][j]); } } } } 其中,n表示矩阵的大小,graph为传递闭包矩阵,使用“||”表示逻辑“或”操作,使用“&&”表示逻辑“与”操作。 调用该函数即可求解传递闭包传递闭包矩阵中的元素为1表示两个节点之间存在路径,为0表示不存在路径。 ### 回答2: Warshall算法是经典的求解传递闭包算法,它是一种基于动态规划的算法。在C语言中,实现Warshall算法需要实现以下几个步骤: Step1:定义矩阵 首先,我们需要定义一个n*n的矩阵来存储图的连接矩阵(邻接矩阵)。 #define N 100 int graph[N][N]; //存储连接矩阵 Step2:初始化图 根据需求,我们需要初始化图,使得所有的边都被标记为false。 for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ graph[i][j]=false; } } Step3:构建连接矩阵 接下来,我们需要根据输入的边信息,构建连接矩阵。 for(int i=0;i<m;i++){ int u,v; scanf("%d%d",&u,&v); graph[u][v]=true; } Step4:求解传递闭包 最后,我们需要使用Warshall算法求解传递闭包。 for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ graph[i][j]|=graph[i][k]&graph[k][j]; } } } 以上代码中,k表示中间点,i和j分别表示起点和终点。最终得到的graph即为传递闭包。 总结 通过以上四个步骤,我们可以实现Warshall算法来求解传递闭包Warshall算法的时间复杂度为O(n^3),在大多数情况下是足够快的。而且,由于其动态规划的思想,可以避免重复计算,提高了运行效率。 ### 回答3: Warshall算法是用来求解传递闭包的一种经典算法,它是基于矩阵乘法的思想,通过对一个矩阵不断地进行运算,最终得到该关系的传递闭包。在C语言实现Warshall算法的过程如下: 1. 定义两个二维数组M和T,用来存储原始的关系矩阵和传递闭包矩阵。其中,M[i][j]表示从i到j是否存在一条边,T[i][j]表示从i到j是否存在一条路径。 2. 根据输入的边的信息,初始化矩阵M。例如,如果输入的边为(1,2),则M[1][2]赋值为1,表示从1到2存在一条边。 3. 对矩阵T进行初始化,将其赋值为矩阵M。 4. 利用Warshall算法不断更新矩阵T,直到得到传递闭包矩阵为止。具体的更新过程如下: for (k = 0; k < n; k++) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { T[i][j] = T[i][j] || (T[i][k] && T[k][j]); } } } 5. 输出传递闭包矩阵T,其中T[i][j]为1表示从i到j存在一条路径,为0表示不存在。 总的来说,Warshall算法是一种高效的算法,它的时间复杂度为O(n^3),适用于较大规模的关系矩阵。在实际应用中,它常被用来处理网络中的路由问题,或者在数据库中优化查询语句。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灼榆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值