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算法能体现出优越性。

总结一下,对于同样矩阵上的一个所求关系的元素,一般算法需要的操作为n*(n-1),而warshall算法仅仅需要n次!

warshall例子:同样对于a,b,c,d,e∈A,关系集合R,若(a,b)(b,c)(c,d)(d,e)∈R,先把a作为中间元素,关系集合没变,

再是b,多了(a,c)∈R,再c,(a,d),再d,(a,e)。算法与中间元素的遍历顺序没有关系,因为开始时,路线起始点确定了,遍历元素只确定传递关系。

转载于:https://www.cnblogs.com/Jimmy-hacks/p/9733373.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值