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)。算法與中間元素的遍歷順序沒有關系,因為開始時,路線起始點確定了,遍歷元素只確定傳遞關系。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM