基于邻接矩阵,有向图的环路检测

来源:操作系统死锁的检测部分,学到一个死锁检测算法,模型基于邻接矩阵,检测有向图是否存在环路。

前提描述: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!!!删博警告)

posted @ 2018-10-16 17:11  PaintChen  阅读(4805)  评论(0编辑  收藏  举报