基於鄰接矩陣,有向圖的環路檢測


來源:操作系統死鎖的檢測部分,學到一個死鎖檢測算法,模型基於鄰接矩陣,檢測有向圖是否存在環路。

前提描述:n個進程,用鄰接矩陣描述他們之間的依賴關系,如果R1需要R2先釋放資源,那么在矩陣中記為1。對於一個3個進程的情況,如下圖所示:

R0、R1、R2之間相互等待於是構成了死鎖,在圖中的效應就是構成了環路,我們要通過矩陣的運算,證明某個矩陣是否存在環路。

算法模型:for k:=1 to n do:

      for i:=1 to n do:

       for j:=1 to n do:

       b[i][j]:=b[i][j]V(b[i][k]Λb[k][j]);          //V相當於“或”運算,Λ相當於“與”運算。

我的理解、分析:i、j是對矩陣兩個坐標的描述,k是什么呢?我理解的是”橋“,Ri通過Rk能到達Rj,則標記b[i][j]為1。我將從公式和程序驗證的角度進行說明:

  程序的驗證,選用C語言進行模擬(ps:我的循環起點是零,但不影響結果,以下的分析都是以0為起點)

  

 1 #include <stdio.h>
 2 #define mapsize 3
 3 int b[mapsize][mapsize] = { {0,1,0},{0,0,1},{1,0,0} };
 4 void mapout() {
 5     int i, j;
 6     for (i = 0; i < mapsize; i++) {
 7         for (j = 0; j < mapsize; j++) {
 8             printf("%d ", b[i][j]);
 9         }
10         printf("\n");
11     }
12 }
13 int main() {
14     int k, i, j, n;
15     n = mapsize;
16     for (k = 0; k < n; k++) {
17         for (i = 0; i < n; i++) {
18             for (j = 0; j < n; j++) {
19 
20                 printf("b[%d][%d]=b[%d][%d]||(b[%d][%d]&&b[%d][%d])=", i, j, i, j, i, k, k, j);
21                 b[i][j] = b[i][j] || (b[i][k] && b[k][j]);
22                 printf("%d\n",b[i][j]);
23 
24             }
25         }
26         printf("--------------------------------\n");
27         mapout();
28     }
29     return 0;
30 }

 

當k=0時,矩陣運算后的結果如下圖,“橋”,R2通過R0到達R1,標記b[2][1]=1。

當k=1時,矩陣運算后結果如下圖,“橋”,R0通過R1能到達R2,標記b[0][2]=1;R2通過R0、R1能到達R2,標記b[2][2]=1。(列舉到這里,相信你已經有所體會,所以我偷懶少寫點)

運算的最終結果b[i][j]代表Ri能到達Rj,根據回路的定義“V0=Vk的通路”(V0起點,Vk終點),所以死鎖存在判斷的依據是,結果矩陣中是否存在b[i][i]=1(在死鎖判斷中,b[i][j]=b[j][i]也具有說服力,可以說明死鎖特征的相互等待情況)。

  公式驗證,簡單說一下,R0到R2,要么R0直連R2,要么R0->R1->R2,用數學語言描述為:b[0][2]=1或者(b[0][1]=1且b[1][2]=1),結合0、1運算特性,公式:b[i][j] = b[i][j] || (b[i][k] && b[k][j]);

k在這里就是1,是個“橋”。(如果老師問你,你回答k是“橋”,然后GG了,本人不負責任)

 

 

 

環路檢測的話,多是使用的深度遍歷、廣度遍歷的搜索方法。兩種方法的時間復雜度是O(n^2),顯然優於三層循環方法。 (寫到這里,似乎上學期算法課,當時的老師沒講清楚,我分析過一波K!!!刪博警告)


免責聲明!

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



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