Warshall算法C语言实现
Floyd-Warshall算法
Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。
使用条件&范围通常可以在任何图中使用,包括有向图、带负权边的图。
Floyd-Warshall 算法用来找出每对点之间的最短距离。
它需要用邻接矩阵来储存边,这个算法通过考虑最佳子路径来得到最佳路径。
1.注意单独一条边的路径也不一定是最佳路径。
2.从任意一条单边路径开始。
所有两点之间的距离是边的权,或者无穷大,如果两点之间没有边相连。
对于每一对顶点u 和v,看看是否存在一个顶点w 使得从u 到w 再到v 比己知的路径更短。
如果是更新它。
3.不可思议的是,只要按排适当,就能得到结果。
伪代码:// dist(i,j) 为从节点i到节点j的最短距离For i←1 to n doFor j←1 to n dodist(i,j) = weight(i,j)For k←1 to n do // k为“媒介节点”For i←1 to n doFor j←1 to n doif (dist(i,k) + dist(k,j) < dist(i,j)) then // 是否是更短的路径?dist(i,j) = dist(i,k) + dist(k,j)我们平时所见的Floyd算法的一般形式如下:void Floyd(){int i,j,k;for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(dist[i][k]+dist[k][j]<dist[i][j])dist[i][j]=dist[i][k]+dist[k][j];}注意下第6行这个地方,如果dist[i][k]或者dist[k][j]不存在,程序中用一个很大的数代替。
最好写成if(dist[i] [k]!=INF && dist[k][j]!=INF && dist[i][k]+dist[k][j]Floyd算法的实现以及输出最短路径和最短路径长度,具体过程请看【动画演示Floyd算法】。
Warshall算法
Warshall 算法
离散数学中⽤于求传递闭包的⼀种⽅法,求解过程很简单,但⽆奈⼀直记不住,所以就写下这篇,下次忘记再来翻看
题⽬:设A={a,b,c,d},R={<a,b>,<b,a>,<b,c>,<c,d>},求t(R)1、先写出R的关系矩阵
2、
⾸先看第⼀列第⼀列中第⼆⾏为1
所以将第⼀⾏加到第⼆⾏上(注意是逻辑加,即1+1=1)得到
3、
接下来是对M1分析看第⼆列
第⼆列中第⼀⾏和第⼆⾏为1
所以将第⼆⾏分别加到第⼀⾏和第⼆⾏上得到
4、
接下来对M2分析看第三列
第三列中第⼀⾏和第⼆⾏为1
所以将第三⾏分别加到第⼀⾏和第⼆⾏上得到
M 0=⎣⎢⎢⎡0100
10000100
0010⎦
⎥⎥⎤M 1=⎣⎢⎢⎡0100
11000100
0010⎦
⎥⎥⎤M 2=⎣⎢⎢⎡1100
11001100
0010⎦
⎥⎥⎤M 3=⎣⎢⎢⎡1100
11001100
1110⎦
⎥⎥⎤
5、对M3分析
看第四列
第四列中第⼀⾏和第⼆⾏和第三⾏都为1
所以将第四⾏分别加到第⼀⾏、第⼆⾏和第三⾏上
6、
结束所以t(R)=M4
待会会补上算法的代码实现M4=⎣
⎢⎢
⎡11
1
1
1
1
1
1
1
0⎦
⎥⎥
⎤。
warshall算法
warshall算法传递关系闭包算法开始,先把关系集合转化为0,1矩阵,使得⽅便关系运算。
对于⼀般算法,通过矩阵点乘的来迭代的⽅式得到传递关系闭包的集合。
代码如下:typedef struct matrix{//定义关系矩阵int n;int a[10][10];}Matrix;Matrix getTranstiveClosure(Matrix matrixA,int matrix_n){for(int num=1;num<matrix_n;num++){//R^n,迭代n-1次按照C语⾔,0号位置为数组第⼀位for(int i=0;i<matrix_n;i++){//开始矩阵布尔积运算for(int j=0;j<matrix_n;j++){for(int k=0;k<matrix_n;k++){if(matrixA.a[i][j]==0)//优化或运算matrixA.a[i][j]=(matrixA.a[i][k]&matrixA.a[k][j]);}}}}return matrixA;}//M=getTranstiveClosure(matrixA);来得到传递闭包矩阵其中矩阵点乘的算法复杂度为O(n^3),迭代次数为n-1次(得到R^n为结果),算法复杂度为O(n^4)。
对于此类算法,特点为为了找到某⼀关系(a,b),要把其他的元素作为中间元素来判断是否存在传递关系。
例如:a,b,c,d,e属于A集合,R为A的关系集合,为了找到(a,b),需要把c,d,e作为中间元素,如假设(a,c)(c,b)∈R,(a,c)(c,b)->(a,b)∈R来得到传递关系。
简⾔之,针对所求的关系,去遍历中间元素的关系去判断。
下⾯我们来看看warshall算法。
代码如下:Matrix warshall(Matrix matrixB,int matrix_n){for(int k=0;k<matrix_n;k++){//K值选择中间量的元素来补全传递关系的路线for(int i=0;i<matrix_n;i++){//遍历新矩阵for(int j=0;j<matrix_n;j++){if(matrixB.a[i][j]==0){//优化或运算matrixB.a[i][j]=matrixB.a[i][k]&matrixB.a[k][j];}//如(a->b)&(b->c)-->(a->c)的关系}}}}warshall算法的算法复杂度为O(n^3),其巧妙之处就在于⽆需矩阵的迭代,通过固定中间元素来进⾏判断关系,并对中间元素逐次遍历,并对传递关系进⾏迭代,需要遍历的中间元素为n个,所求矩阵遍历操作为n^2,在n规模⾜够⼤的时候warshall算法能体现出优越性。
warshall算法
——Warshall算法求二元关系的传递闭包t(R)设A={V1,V2,V3......Vn},t(R)=R1∪R2∪R3……Rn (n为集合A中元素的个数)——根据路径中所经过的节点数来推导递推公式,由递推公式计算Rn,即t(R)依次讨论Vi与Vj经过中间点(V1),(V1,V2),(V1,V2,V3),(V1,V2,V3…Vn)的情况且它们之间存在关系:后面讨论的情况总是包含前一项讨论的情况将A中的元素进行编号,例如:V1---1,V2---2,V3---3,Vn---n设Vi∈R Vj∈R定义R(k) 表示Vi 与Vj之间所经过节点的个数为k时的传递的集合R(0)=R 表示Vi 与Vj之间不经过节点的传递的集合R(1)表示Vi 与Vj之间经过第一个节点V1,若R(1)=1,说明Vi与Vj是连通的,若R(1)=0,说明Vi与Vj是不连通的有2条路径R(2)表示Vi与Vj之间经过第二个节点V2,且存在两个中间点V1,V2,有3条路径…………R(n)表示A中的所有元素都作为中间点,Vi与Vj之间有n条路径即Vi 不少于编号个数k的中间点的集合C Vj——递推关系(由R(k-1)推导R(k))设Vk ,表示Vi与Vj之间可能存在的节点k=1,2,3……n①Vk ∈C时此时Vi与Vj是否存在传递关系取决于Vi到Vk,Vk到Vj是否存在,若两者都存在,则Vi 中间点的集合C1 Vk 中间点的集合C2 VjRij(k)=Rik(k-1)∩Rkj(k-1)递推 2次②Vk ∈/C(不属于)时此时不在讨论的范围之内,Vi与Vj之间不存在新的连通关系,所以此时的Rij与上一次的相同,从而达到保留原来已算出的传递关系的目的Vi 不少于编号个数k的中间点的集合C VjRij(k)=Rij(k-1)综上所述,递推关系为:Rij(k)= Rij(k-1)∪{Rik(k-1)∩Rkj(k-1)}(为1)源代码#include<iostream.h>void main(){int i,j;int const n=4; //n为矩阵的阶数,可在此处改写int m[n][n];for(i=0;i<n;i++)for(j=0;j<n;j++)m[i][j]=0;int a,b,c; //输入关系矩阵Rcout<<"请输入矩阵"<<endl;c=1;while(c){cout<<"请分别输入矩阵中为1的行数和列数:"<<endl;cin>>a>>b;m[a-1][b-1]=1;cout<<"继续输入关系请按1,输入完成请按0"<<endl;cin>>c;}cout<<"输出关系矩阵R:"<<endl;for(i=0;i<n;i++){for(j=0;j<n;j++)cout<<m[i][j];cout<<endl;}int k; //warshall算法for(k=0;k<n;k++)for(i=0;i<n;i++)for(j=0;j<n;j++)if(m[i][j]==1||m[i][k]==1&&m[k][j]==1)m[i][j]=1;cout<<"R传递闭包是:"<<endl;for(i=0;i<n;i++){for(j=0;j<n;j++)cout<<m[i][j];cout<<endl;}}可执行文件。
Floyd-Warshall算法详解
Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3)。
我们平时所见的Floyd算法的一般形式如下:1void Floyd(){2int i,j,k;3for(k=1;k<=n;k++)4for(i=1;i<=n;i++)5for(j=1;j<=n;j++)6if(dist[i][k]+dist[k][j]<dist[i][j])7 dist[i][j]=dist[i][k]+dist[k][j];8}注意下第6行这个地方,如果dist[i][k]或者dist[k][j]不存在,程序中用一个很大的数代替。
最好写成if(dist[i][k]!=INF && dist[k][j]!=INF && dist[i][k]+dist[k][j]<dist[i][j]),从而防止溢出所造成的错误。
上面这个形式的算法其实是Floyd算法的精简版,而真正的Floyd算法是一种基于DP(Dynamic Programming)的最短路径算法。
设图G中n 个顶点的编号为1到n。
令c [i, j, k]表示从i 到j 的最短路径的长度,其中k 表示该路径中的最大顶点,也就是说c[i,j,k]这条最短路径所通过的中间顶点最大不超过k。
因此,如果G中包含边<i, j>,则c[i, j, 0] =边<i, j>的长度;若i= j ,则c[i,j,0]=0;如果G中不包含边<i, j>,则c (i, j, 0)= +∞。
c[i, j, n] 则是从i 到j 的最短路径的长度。
对于任意的k>0,通过分析可以得到:中间顶点不超过k 的i 到j 的最短路径有两种可能:该路径含或不含中间顶点k。
若不含,则该路径长度应为c[i, j, k-1],否则长度为c[i, k, k-1] +c [k, j, k-1]。
Floyd—Warshall算法的C语言实现
0 引 言
最 短 路 是 图 论 研 究 中 的 一 个 经 典 算 法 问题 。 最 短 路 问 题 , 般 来 说 就 是 从 给 定 的 网 络 中 找 出 任 意 一 两 点 之 间 距 离 最 短 的 一 条 路 径 。 这 里 说 的 距 离 是 权 数 的 代 称 , 实 际 的 网 络 中 , 数 可 以是 时 间 、 用 在 权 费
为 与 ,的 距 离 。
Fly o d~ W a s al 法 可 求 每 对 顶 点 之 间 最 短 距 离 ,g中 的 权 可 为 负 值 , 不 可 以 有 带 负 权 的 圈 。 rh l算 ; I 但
Fly o d~ W a s al 法 的 描 述 如 下 : rh l算
20 0 8年 l 月 1
安庆 师 范学 院学报 ( 自然科 学版)
Jun l f n i e cesC l g ( aua S i c d in o ra o qn T a h r ol e N trl c neE io ) A g e e t
NO 2 0 V. 0 8
E , 应 一 个 实 数 叫 称 为 弧 上 的 “ ” 通 常 把 这 种 赋 权 的 图 称 为 赋 权 图 或 网 络 。 对 权 。 定 义 3 对 于 赋 权 有 向 图 D 一 (/ E) 其 中 边 有 权 一¨ 构 造 矩 阵 U 一 ( d , 中 : 、, , r ) 其
定 义 2 在实 际应 用 中 , 定 一个 图 G一 ( , 给 E)或 有 向 图 D 一 ( , , V 中 指 定 两 个 点 , 个 称 V E) 在 一 为 始 点 ( 发 点 ) 记 作 , 一 个 称 为 终 点 ( 收 点 ), 作 , 余 的 点 称 为 中 间 点 。 每 一 条 弧 ( , ) ∈ 或 , , 或 记 其 对
Warshall传递闭包算法的学习与实现
Warshall传递闭包算法的学习与实现1、问题引⼊ ⼀个有n个顶点的有向图的传递闭包为:有向图中的初始路径可达情况可以参见其邻接矩阵A,邻接矩阵中A[i,j]表⽰i到j是否直接可达,若直接可达,则A[i,j]记为1,否则记为0;两个有向图中i到j有路径表⽰从i点开始经过其他点(或者不经过其他点)能够到达j点,如果i到j有路径,则将T[i,j]设置为1,否则设置为0;有向图的传递闭包表⽰从邻接矩阵A出发,求的所有节点间的路径可达情况,该矩阵就为所要求的传递闭包矩阵。
例如:有向图为:由该有向图可以得到初始的邻接矩阵为:那么warshall传递闭包算法的⽬的就是由邻接矩阵出发,进⾏探索求出最终的传递闭包:2、动态规划求解思路 动态规划将问题分段,本例warshall算法是通过⼀系列n阶矩阵r(k)来构造最终阶段n阶传递闭包矩阵r(n) R(k) 由它的前趋 R(k-1) 计算得到(分级推进计算)。
R(0) ——该矩阵不允许它的路径中包含任何中间顶点,即从该矩阵的任意顶点出发的路径不含有中间顶点,此即邻接矩阵。
R(1) ——允许路径中包含第1个顶点(本例编号 1)作为中间顶点。
R(2) ——允许路径中包含前2个顶点(本例编号1 2)作为中间顶点。
R(k) ——允许路径中包含前k个顶点作为中间顶点。
R(n) ——允许路径中包含全部 n 个顶点作为中间顶点。
每个后继矩阵 R(k) 对其前趋 R(k-1) 来说,在路径上允许增加⼀个顶点,因此有可能包含更多的1(增加前为1的在增加后依然为1)。
3、具体的算法描述1 warshall(A[1...n,1...n]2 r(0)<-A;3for(k=1;k<=n;k++)4for(i=1;i<=n;i++)5for(j=1;j<=n;j++)6 r(k)[i,j]=r(k-1)[i,j] or(r(k-1)[i,k] and r(k-1)[k,j]);7return r(n);4、具体实现代码如下 说明:(1)有向图的顶点个数和初始邻接矩阵存储在2.txt中(具体如下图),其中4表⽰有向图中有4 个顶点,其他表⽰初始邻接矩阵。
C语言常用的入门算法
C语言常用的入门算法C语言是一门广泛应用于计算机科学和软件开发领域的编程语言。
作为一门通用的编程语言,C语言提供了丰富的算法和数据结构库,使得开发人员能够解决各种不同类型的问题。
下面是C语言入门算法的一些常见示例:1.排序算法:-冒泡排序:通过不断比较相邻的元素,并交换它们的位置来排序。
-插入排序:将未排序的元素逐一插入已排序的列表中。
-选择排序:通过重复找到最小的元素并将其放置在已排序序列的末尾来排序。
-快速排序:通过选择一个基准元素,将列表划分成较小和较大的两部分,然后对其进行递归排序。
-归并排序:将列表分成较小的子列表,然后逐个合并这些子列表。
2.查找算法:-顺序查找:逐个比较列表中的元素,直到找到匹配的元素为止。
-二分查找:在已排序的列表中通过递归或循环的方式,将待查找的元素与中间元素进行比较,以确定它可能在哪一半中。
-哈希表:通过散列函数将元素映射到一个较小的固定大小的数组(哈希表)中,并通过索引快速查找。
3.字符串算法:-字符串长度:使用循环逐个字符遍历,直到遇到字符串结束符'\0'为止,统计字符个数。
-字符串比较:逐个字符比较两个字符串的对应位置,直到遇到不相等的字符或字符串结束符。
-字符串拼接:将一个字符串的字符逐个复制到另一个字符串的末尾,直到遇到字符串结束符'\0'。
-子字符串匹配:在一个较长的字符串中查找一个较短的子字符串,常用的算法有朴素算法和KMP算法。
4.数值算法和运算:-求和、平均值、最大/最小值:循环遍历列表,累加求和,计算平均值,找出最大/最小值。
-阶乘和斐波那契数列:使用循环或递归计算给定数字的阶乘和斐波那契数列。
-幂运算和开方:通过循环或递归计算给定数字的幂和开方。
- 线性方程求解:求解形如ax + b = 0的一元线性方程。
5.图算法:-广度优先(BFS):通过遍历图的邻居节点来逐层扩展区域,通常用于查找最短路径。
-深度优先(DFS):通过遍历图的邻居节点来递归到达所有可能的节点,通常用于查找所有路径、拓扑排序等。
华氏算法
Warshall算法
一、Warshall算法的基本思想
1.算法功能:计算图的传递闭包。 2.对每个结点(从第一列开始),找出所有 具有到此结点的有向边的结点(即该列中元 素为1的所在行的结点),再将这些结点所 在行同该结点所在行进行逻辑加后作为这些 结点所在的新行(添加新的有向边)(反映 了如果这些结点没有到其它结点的有向边, 但有到该结点的有向边,再通过该结点间接 到达其它结点,根据传递闭包的定义,这些 结点就必然有一条有向边到达其它结点。)
二、代码:
For(i=0;i<n;i++) For(s=0; s<n;s++) For(t=0; t<n;t++) If(A[s][i]&& A[i][t]) A[s][t]=1; 其中n为有向图的对应矩阵的阶数,s为 第s行,t为第t列,i为随机整数。
三、实验源代码
四、试验结果截图:
五、实验心得
通过查阅相关资料,我终于对华氏算法有 了一定的了解和掌握。起初只是浅层次的 了解,对于细节并不是很清楚,但通过我 翻阅相关书籍以及和同得一门学科或知识的最大魅力不 仅仅是它所覆盖的内容,更是研究学习过 程中所带来的快乐与收获。对华氏算法的 学习研究,激发了我对离散和计算机应用 的兴趣,给予了我很大的鼓励。
} } } } printf("可传递闭包关系矩阵是:\n"); for(i=0;i<k;i++) { for(j=0;j<n;j++) { printf("%d", temp[i][j]); } printf("\n"); } } void main() { printf("利用Warshall算法求二元关系的可传递闭包\n"); void warshall(int,int); int k , n; printf("请输入矩阵的行数i: "); scanf("%d",&k); printf("请输入矩阵的列数j: "); scanf("%d",&n); warshall(k,n); }
用warshall算法求传递闭包离散数学
用warshall算法求传递闭包离散数学传递闭包是关系代数中的一种操作,它可以帮助我们寻找一组关系中所有可能的传递关系。
在这篇文章中,我们将介绍Warshall算法,它是一种使用动态规划策略来计算传递闭包的算法。
通过解释这个算法的思想和实现过程,我们可以更好地理解传递闭包的概念。
在关系代数中,关系是一个有序对的集合。
对于一个关系R,如果存在一对元素(a,b),并且存在一对元素(b,c),那么我们可以说存在一对元素(a,c)。
这种传递性关系被称为传递关系。
传递闭包则是从给定的关系中计算出所有可能的传递关系。
Warshall算法的思想是通过迭代计算,从初始的关系开始逐步扩展,直到完成传递闭包的计算。
算法的过程如下:1.初始化:假设我们有一个n×n的关系矩阵R,其中n是关系的元素数量。
我们创建一个n×n的矩阵T,并初始化为关系矩阵R的拷贝。
2.迭代计算:我们通过迭代计算来更新矩阵T,直到没有新的传递关系可以添加为止。
迭代的过程如下:a.对于矩阵T的每一对元素(T[i,j]),如果存在一对元素(T[i,k])和(T[k,j]),并且(T[i,j])的值为0,那么我们将(T[i,j])的值设置为1b.继续迭代上述步骤,直到整个矩阵T不再发生任何改变。
3.输出结果:我们将矩阵T作为传递闭包的结果。
通过上述步骤,我们可以计算出给定关系的传递闭包。
下面我们将通过一个示例来说明Warshall算法的操作过程。
假设我们有一个关系R,其中包含以下有序对:{(a,b),(b,c),(c,d)}。
我们的任务是计算出关系R的传递闭包。
首先,我们创建一个3×3的关系矩阵R:R=,0100000接下来,我们创建一个3×3的矩阵T,将其初始化为关系矩阵R的拷贝:T=R=,0100000开始迭代计算,我们按照算法的第2步进行操作,直到矩阵T不再发生改变:第一次迭代:根据矩阵T的第一列计算矩阵T的第一行:T[1,1] = T[1,1] or (T[1,2] and T[2,1]) = 0 or (1 and 0) = 0 T[1,2] = T[1,2] or (T[1,3] and T[3,2]) = 1 or (0 and 0) = 1 T[1,3] = T[1,3] or (T[1,1] and T[3,3]) = 0 or (0 and 0) = 0根据矩阵T的第二列计算矩阵T的第二行:T[2,1] = T[2,1] or (T[2,2] and T[2,1]) = 0 or (0 and 1) = 0T[2,2] = T[2,2] or (T[2,3] and T[3,2]) = 0 or (1 and 0) = 0T[2,3] = T[2,3] or (T[2,1] and T[3,3]) = 1 or (0 and 0) = 1根据矩阵T的第三列计算矩阵T的第三行:T[3,1] = T[3,1] or (T[3,2] and T[2,1]) = 0 or (0 and 0) = 0T[3,2] = T[3,2] or (T[3,3] and T[3,2]) = 0 or (0 and 1) = 0T[3,3] = T[3,3] or (T[3,1] and T[1,3]) = 0 or (0 and 0) = 0第一次迭代结束后,矩阵T的值不再发生改变。
c语言经典算法题
c语言经典算法题
C语言经典算法题目涵盖了多个领域,包括排序、查找、递归、动态规划等。
以下是一些经典的C语言算法题目,它们对于提高编程能力和理解算法思想都是很有帮助的:
1. 冒泡排序:
实现冒泡排序算法,对一个数组进行升序或降序排序。
2. 快速排序:
实现快速排序算法,对一个数组进行升序或降序排序。
3. 选择排序:
实现选择排序算法,对一个数组进行升序或降序排序。
4. 二分查找:
实现二分查找算法,在有序数组中查找一个特定的元素。
5. 递归:
编写一个递归函数,计算斐波那契数列的第n 个数字。
6. 动态规划:
解决经典的动态规划问题,比如背包问题、最长公共子序列等。
7. 链表反转:
反转一个单链表或双链表。
8. 树的遍历:
实现二叉树的前序、中序和后序遍历。
9. 图的深度优先搜索(DFS)和广度优先搜索(BFS):
实现图的深度优先搜索和广度优先搜索算法。
10. 最短路径算法:
实现Dijkstra算法或Floyd-Warshall算法来求解图中的最短路径。
11. 素数判断:
编写一个函数判断一个给定的数是否是素数。
12. 最大公约数和最小公倍数:
实现求两个数的最大公约数和最小公倍数的算法。
这些题目旨在帮助你熟悉常见的算法思想和数据结构,提高编程和问题求解的能力。
解决这些题目时,不仅要注重正确性,还要考虑算法的效率和优化。
c语言求二元关系的闭包用warshall算法
C语言求二元关系的闭包用Warshall算法一、概述在离散数学和图论中,二元关系是研究对象之间的重要概念。
闭包是一个关系的扩张,它包含了原关系中的所有元素关系及其推导出来的新的元素关系。
二、二元关系的定义和性质1. 二元关系的定义在集合A上的二元关系R是一个A × A的子集,即元素是有序对(a, b) ,其中a、b∈A。
若(a, b)∈R,则称a和b有关系,记为aRb;若(a, b)∉R,则称a和b 没有关系。
2. 二元关系的性质- 自反性:若∀a∈A,则(a, a)∈R- 对称性:若∀a, b∈A,若(a, b)∈R,则(b, a)∈R- 传递性:若∀a, b, c∈A,若(a, b)∈R,(b, c)∈R,则(a, c)∈R三、Warshall算法介绍Warshall算法是由美国计算机科学家Floyd Warshall提出的,它用于寻找图的传递闭包。
该算法可以在一个图的邻接矩阵中查找出图的任意两个顶点之间是否有路径的传递闭包。
四、C语言实现二元关系的闭包在C语言中,我们可以使用Warshall算法来实现对二元关系的闭包的求解。
下面是一个示例代码的算法:```c#include<stdio.h>void warshall(int n, int arr[10][10]) {int i, j, k;for(k = 0; k < n; k++) {for(i = 0; i < n; i++) {for(j = 0; j < n; j++) {if(arr[i][j] || (arr[i][k] arr[k][j])) {arr[i][j] = 1;}}}}}int m本人n() {int n, i, j, arr[10][10];printf("Enter the number of elements in set A: "); scanf("d", n);printf("Enter the relation matrix: \n");for(i = 0; i < n; i++) {for(j = 0; j < n; j++) {scanf("d", arr[i][j]);}}warshall(n, arr);printf("The transitive closure is: \n");for(i = 0; i < n; i++) {for(j = 0; j < n; j++) {printf("d ", arr[i][j]);}printf("\n");}return 0;}```五、代码解析1. 首先定义了一个warshall()函数,它的参数包括元素数量n和一个二维数组arr[][],表示二元关系的矩阵。
warshall算法求传递闭包离散数学
warshall算法求传递闭包离散数学Warshall算法是一种用于求解传递闭包的经典算法,在离散数学中非常常见和重要。
传递闭包是一个二元关系的重要概念,给定一个关系R,传递闭包就是一个关系R+,它包含由R导出的所有传递关系,也就是如果存在元素a和元素b,且有一个序列元素a=r_1,r_2,...,r_k=b,其中r_1,r_2,...,r_k属于R,那么就有a R+ b。
换句话说,传递闭包包含了R中的所有传递关系。
Warshall算法可以用来求解关系的传递闭包。
这个算法的基本思想是以动态规划的方式逐步计算关系的传递闭包。
具体步骤如下:
1. 初始化一个n×n矩阵T,其中n是关系的元素个数。
如果关系中的元素i和元素j之间有关系R,则T[i][j]=1,否则T[i][j]=0。
2. 对于矩阵T中的每一对不同的元素i和j,检查是否存在第三个元素k,使得T[i][k]=1且T[k][j]=1。
如果存在,则将T[i][j]设为1,代表元素i和元素j之间存在传递关系。
如果不存在,则保持T[i][j]的原始值。
3. 重复步骤2,直到矩阵T不再变化为止。
此时,矩阵T即为原始关系的传递闭包。
通过Warshall算法,可以高效地求解关系的传递闭包。
该算法的时间复杂度为O(n^3),其中n为关系的元素个数。
需要注意的是,Warshall算法要求关系R的元素是有限离散的,而且关系的元素个数不能太大,否则算法的计算时间会非常长。
warshall方法
warshall方法
Warshall算法,也称为Floyd-Warshall算法,是一种用于寻找加权图中所有顶点对之间最短路径的动态规划算法。
该算法可以处理有向图或无向图,并且可以处理负权边,但不可以处理负权环路。
Warshall算法的基本思想是利用动态规划的思想,通过递推的方式来不断更新顶点对之间的最短路径。
具体来说,算法首先初始化一个二维数组来表示顶点对之间的最短路径,然后通过不断更新这个数组来找到最短路径。
算法的步骤如下:
1. 初始化一个二维数组D,其中D[i][j]表示顶点i到顶点j 的最短路径长度。
2. 对于每一对顶点i和j,如果存在顶点k使得从i到j的路径经过k比直接从i到j的路径更短,那么更新
D[i][j]=D[i][k]+D[k][j]。
3. 重复以上步骤,直到所有顶点对之间的最短路径都被找到。
Warshall算法的时间复杂度为O(n^3),其中n表示图中顶点的个数。
这意味着对于大型图来说,算法的运行时间可能会比较长。
总的来说,Warshall算法是一种非常有效的寻找图中所有顶点对之间最短路径的算法,尤其适用于稠密图。
然而,对于稀疏图来说,可能存在更加高效的算法来解决这个问题。
可达矩阵的Warshall算法实现
3 2
安徽大学学报 ( 自然科学 版)
第3 5卷
图 1所示 为一 有 向图 , 称矩 阵 A 为有 向图 G的邻 接矩 阵 则
VI V2
V4
V3
图 1 有 向图 G
F g 1 Die t d g a h i. rce r p
l
2
3
4
5
1
21 0 1年 7月
安徽 大学学报(自然科学 版)
Junl f n u U ie i ( a rl cec dt n o ra o A h i n r t N t a S i eE io ) v sy u n i
J l 0 1 uy2 1
Vo . 5 No 4 13 .
第3 5卷 第 4期
可达矩 阵的 Wasa 算法 实现 rh l l
叶 红
( 安徽工业 大学 计算机学院 , 安徽 马鞍山 摘 2 30 ) 4 0 0
要: 通过图的矩阵表示可 以得 到图的很 多重要性 质 , 邻接 矩阵看作 图 的结 点集 的关 系矩 阵 , 将
由此可 以产生可达矩 阵 , 从而可 以反 映图中各结 点间是 否有路 . 达矩 阵可用 Wasa 算 法求得 , 可 r l hl 作者 用V B实现 了该算法 . 关键词 : 图的矩阵 ; 邻接矩 阵 ; r al 法 ; B; Was l算 h V 可达矩 阵
阵 也可 以用Βιβλιοθήκη Wa hl算法 计算 得 到. ra s l
1 相 关 定 义 和 定 理
定义 1 设 G= , ) ( E 是一简单有向图, 结点集为 = , , , ). { … 构造矩阵 A=( … , 中: 口) 其
Warshall算法C语言实现
Warshall在1962年提出了一个求关系的传递闭包的有效算法。
其具体过程如下,设在n 个元素的有限集上关系R的关系矩阵为M:(1)置新矩阵M;(2)置k=1;(3)对所有i如果Mi,k]=1,则对j=1..n执行:M[i,j]←M[i,j]*M[k,j];(4)k增1;(5)如果k≤n,则转到步骤(3),否则停止。
所得的矩阵A即为关系R的传递闭包t(R)的关系矩阵。
下面是warshall算法的C语言实现#include<stdio.h>#define N 100void main(){int i,j,k,n,M[N][N];printf("输入矩阵阶数,以回车结束:");scanf("%d",&n);//输入矩阵阶数printf("输入矩阵,以空格间隔:\n");for(i=1;i<=n;i++)//输入矩阵{for(j=1;j<=n;j++)scanf("%d",&M[i][j]);}for(k=1;k<=n;k++)//Warshall矩阵运算for(i=1;i<=n;i++)for(j=1;j<=n;j++){M[i][j]=M[i][j]+M[i][k]*M[k][j];if(M[i][j]!=0)M[i][j]=1;}printf("输出传递闭包矩阵:\n");for(i=1;i<=n;i++)//输出传递闭包{for(j=1;j<=n;j++){printf("%d ",M[i][j]);}printf("\n");}printf("厦大的离散作业,亲~\n");}。
C++代码Warshall算法
/*==========================================================*/ /*Warshall算法*//*Warshall在1962年提出了一个求关系的传递闭包的有效算法。
*//*其具体过程如下,设在n个元素的有限集上关系R的关系矩阵为M:*//*(1)置新矩阵A=Mr; *//*(2)置i=1; *//*(3)对所有j如果A[j,i]=1,则对k=1..n执行:*//* A[j,k]:A[j,k]+A[i,k]; *//*(4)i = i + 1; *//*(5)如果i≤n,则转到步骤(3),否则停止。
*//*所得的矩阵A即为关系R的传递闭包t(R)的关系矩阵。
*//*用Warshall算法求有限集合上二元关系的传递闭包:*//************************************************************//*课本p89页:*//*Warshall算法*//*以例4.3.6 为例求传递闭包,验证程序的结果。
*//* 将4 */* R = {<a,b>,<b,a>,<b,c>,<c,d>} 置于f:\\临时\\b.txt *//*==========================================================*/ #include<iostream>#include<fstream>#include<string>using namespace std;void main(){ifstream in("f:\\临时\\b.txt");int x,y,i,j,k;int N;in>>N;string strA,strB;in>>strA;//提取关系中的元素存入strBfor(x = 0;x < strA.size();x++)if(strA[x] >= 'a' && strA[x] <= 'z')strB += strA[x];//申请二维数组空间int **A = new int*[N];//for(x = 0;x < N;x++)A[x] = new int[N];//置新矩阵A=0for (x = 0;x < N; x++)for (y = 0;y < N;y++)A[x][y] = 0;//置新矩阵A=Mr;for(x = 0;x < strB.size();x += 2)A[strB[x]-'a'][strB[x+1]-'a'] = 1;cout<<"矩阵A:\n";for (x = 0;x < N;x++){for (y = 0;y < N;y++)cout<<A[x][y]<<" ";cout<<endl;}i = 0;//置i=1;while(i < N){for (j = 0;j < N;j++)//对所有jif (A[j][i] == 1)//如果A[j,i]=1for (k = 0;k < N;k++)//则对k=1..n执行:if(A[j][k] == 1 || A[i][k] == 1)A[j][k] = 1;i++;}cout<<"传递闭包:\n";for (x = 0;x < N;x++){for (y = 0;y < N;y++)cout<<A[x][y]<<" ";cout<<endl;}delete A;}。
c语言实现弗洛伊德算法
c语言实现弗洛伊德算法弗洛伊德算法,也称为Floyd-Warshall算法,是一种用于求解所有节点对之间最短路径的动态规划算法。
该算法的时间复杂度为O(n^3),适用于有向图或无向图,可以处理负权边但不能处理负环。
在C语言中,我们可以使用二维数组来表示图的邻接矩阵,其中matrix[i][j]表示从节点i到节点j的边权值。
我们可以使用三重循环来实现弗洛伊德算法,其中第一重循环枚举中间节点k,第二重循环枚举起点i,第三重循环枚举终点j。
具体实现如下:```cvoid floyd(int n, int matrix[][n]) {int i, j, k;for (k = 0; k < n; k++) {for (i = 0; i < n; i++) {for (j = 0; j < n; j++) {if (matrix[i][k] + matrix[k][j] < matrix[i][j]) {matrix[i][j] = matrix[i][k] + matrix[k][j];}}}}}```在上述代码中,n表示节点数,matrix为邻接矩阵。
我们首先枚举中间节点k,然后枚举起点i和终点j,如果从i到k再到j的路径比当前的i到j路径更短,则更新i到j的路径长度。
最终,matrix[i][j]中存储的就是节点i到节点j的最短路径长度。
需要注意的是,如果图中存在负环,则该算法会陷入死循环。
因此,在实际应用中,我们需要先判断图中是否存在负环,如果存在则无法使用弗洛伊德算法。
弗洛伊德算法是一种非常实用的动态规划算法,可以用于求解所有节点对之间的最短路径。
在C语言中,我们可以使用邻接矩阵来表示图,并使用三重循环来实现该算法。
C语言技术与算法设计结合实例分享
C语言技术与算法设计结合实例分享在计算机科学领域中,C语言是一门被广泛应用的编程语言。
它的灵活性和高效性使得它成为许多软件和系统的首选语言。
然而,单纯的掌握C语言并不足以成为一名出色的程序员。
算法设计是计算机科学中至关重要的一部分,它涉及解决问题的方法和步骤。
本文将探讨C语言技术与算法设计的结合,并通过一些实例来分享这种结合的实际应用。
首先,让我们来看一个简单的实例。
假设我们需要编写一个程序来计算斐波那契数列的第n个数字。
斐波那契数列是一个经典的数学问题,其定义是每个数字都是前两个数字的和。
通过使用C语言的循环和条件语句,我们可以编写一个简单的程序来解决这个问题。
然而,这种方法的效率并不高,特别是当n的值很大时。
为了提高效率,我们可以使用递归算法来解决这个问题。
递归算法是一种将问题分解成更小的子问题并逐步解决的方法。
通过使用递归算法,我们可以大大减少计算时间,提高程序的效率。
接下来,让我们来看一个稍微复杂一些的实例。
假设我们需要编写一个程序来解决旅行商问题。
旅行商问题是一个经典的组合优化问题,其目标是找到一条路径,使得旅行商可以经过所有城市并返回起始城市,同时路径的总长度最短。
这个问题的解决方案需要使用图论和动态规划等算法。
在C语言中,我们可以使用图的数据结构和相关的算法来解决这个问题。
通过使用邻接矩阵或邻接表来表示城市之间的连接关系,并使用最短路径算法(如Dijkstra算法或Floyd-Warshall算法)来计算最短路径,我们可以编写一个高效的程序来解决旅行商问题。
除了以上两个实例,C语言技术与算法设计的结合在许多其他领域也有广泛的应用。
例如,在图像处理中,我们可以使用C语言编写算法来实现图像的滤波、边缘检测和图像压缩等操作。
在网络编程中,我们可以使用C语言编写算法来实现数据包的传输和路由选择等功能。
在人工智能和机器学习领域,我们可以使用C 语言编写算法来实现各种模型和算法,如神经网络、遗传算法和支持向量机等。
warshall算法原理
warshall算法原理
Warshall算法,又称为Floyd-Warshall算法,是解决“全源最
短路径”问题的一种动态规划算法。
在一个有向图中,每个点都有一个编号,假设有n个点,那么图
上所有的边可以用一个n×n的矩阵来表示,称为邻接矩阵。
邻接矩阵
中每个元素a[i][j]表示从i到j有一条边,a[i][j]=1。
如果没有边,则a[i][j]=0。
Warshall算法用动态规划的思想解决全源最短路径的问题。
定义
d[i][j]为从i到j的最短路径长度,k表示所有可能经过的中间点,
则状态转移方程为:d[i][j]=min(d[i][j], d[i][k]+d[k][j])。
其中i,j,k均为图中的点。
算法的步骤如下:
1. 将邻接矩阵复制给d数组。
2. 枚举所有节点k进行中间点的遍历,在此遍历中,如果通过
中间点k能够得到更短的路径,则更新对应的节点i到节点j的距离。
3. 遍历完所有中间节点后,d数组中保存的便是各个点到其他点的最短距离。
Warshall算法的时间复杂度为O(n^3),其中n为节点数。
虽然
算法复杂度较高,但是它适用于任意类型的有向图,包括存在负边权
的图,因此在实际使用中还是有一定的应用价值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Warshall在1962年提出了一个求关系的传递闭包的有效算法。
其具体过程如下,设在n 个元素的有限集上关系R的关系矩阵为M:
(1)置新矩阵M;
(2)置k=1;
(3)对所有i如果Mi,k]=1,则对j=1..n执行:
M[i,j]←M[i,j]*M[k,j];
(4)k增1;
(5)如果k≤n,则转到步骤(3),否则停止。
所得的矩阵A即为关系R的传递闭包t(R)的关系矩阵。
下面是warshall算法的C语言实现
#include<stdio.h>
#define N 100
void main()
{
int i,j,k,n,M[N][N];
printf("输入矩阵阶数,以回车结束:");
scanf("%d",&n);//输入矩阵阶数
printf("输入矩阵,以空格间隔:\n");
for(i=1;i<=n;i++)//输入矩阵
{
for(j=1;j<=n;j++)
scanf("%d",&M[i][j]);
}
for(k=1;k<=n;k++)//Warshall矩阵运算
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
M[i][j]=M[i][j]+M[i][k]*M[k][j];
if(M[i][j]!=0)
M[i][j]=1;
}
printf("输出传递闭包矩阵:\n");
for(i=1;i<=n;i++)//输出传递闭包
{
for(j=1;j<=n;j++)
{
printf("%d ",M[i][j]);
}
printf("\n");
}
printf("厦大的离散作业,亲~\n");
}。