有向图的深度优先搜索 —— 找出环路

一、目标

  找出下图(有向图)中的回路

  

 

二、策略

  1,深度优先搜索:顾名思义,就是从某个顶点开始探索,会一直探索到某个可能路径的尽头才会停止探索,并原路返回(下面的例子,

     并不会一直原路返回到原点,而是每次原路返回一个顶点,就会探索从该点向下的所有路径情况,以此类推);

  2,按道理需要从1~7个点都探索一下,看有没有某个回路包含自己;为了简化,我们只从顶点1探索;

  3,假设我手中有个笔记本,分别记录3件事情,如下:

    

   我准备从房间1(如下图)开始探索如下图所示的区域,看能不能发现其中的某个回路(就像鬼打墙那样的回路,会一直路过相同的地方);

  

 

三,实施

  1,我进入房间1,发现有一把钥匙,可以打开房间1中的那两扇门;

     A,然后房间1中还有一个柜子localCycles,我撕了一张空白的纸放进柜子中,准备记录一些东西:

    

 

      B,我在我随身携带的本子上记录如下内容:

     

 

    C,使用这个房间的钥匙去打开一扇未曾打开过的门;

      我使用房间1中的钥匙打开了东边的门,至于为什么选择东边的门而不是南边的门,我想可能是因为我没有强迫症吧,哪扇门都可以,哈哈;

 

       D,我站在两个房间连接的过道上(其实还是在房间1中的),发现下一个是房间3;

      我得先拿出我随身携带的本子,看看有没有这个房间3的相关信息:

    

 

   2,由于本子上并没有房间3的任何信息,所以我走进了房间3;

    并且房间3看起来和房间1是一模一样,只是我并没有发现任何钥匙;

    A,同样的,我会撕下一张空白的纸放进柜子localCycles中:

    

 

    B,我在我随身携带的本子上记录如下内容:

    

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;

       因为我没有任何房间3的钥匙,所以即使房间3有门,我也是打不开的,何况,房间3也没有门;没得办法,没有更深的房间可以去了,这条路算是走到了尽头;

    

     E,所以我在我的本子上记录如下内容:

    

 

      F,我要原路返回(我用脑子记下了我来时的路,也可以记在本子上)了,我得带上房间3柜子里的纸片,因为回到房间1后,还需要用到它;

 

    3,我使用房间1的钥匙又回到了房间1中,我看看上个房间也就是房间3带回来的纸片,发现上面一片空白:

      

 

       我早就想好了,如果这张纸片是空白的,我就在我随身携带的本子上记录如下内容:

     

     然后上个房间带回来的那张之前就没用了,扔了、吃了都随便;

 

     回到房间1之后,我不能闲着,当务之急就是:

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;使用房间1的钥匙打开房间1南边的门,因为我必须探索完这个房间向下的所有的路径;

      

      D,我站在两个房间连接的过道上,发现下一个是房间2;

      我拿出我的本子,看看有没有这个房间2的相关信息:

    

 

    4,由于本子上并没有房间2的任何信息,所以我走进了房间2,并且房间2看起来和之前的房间是一模一样,并且有1把钥匙;

     A,同样的,我会撕下一张空白的纸放进柜子localCycles中;

    

 

     B,我在我的本子上记录如下内容:

     

 

        C,使用这个房间的钥匙去打开一扇未曾打开过的门;我使用房间2中的钥匙打开了东边的门

     

     D,我站在两个房间连接的过道上,发现下一个是房间5;

      我拿出我的本子,看看有没有这个房间5的相关信息:

    

 

   5,由于本子上并没有房间5的任何信息,所以我走进了房间5,并且房间5看起来和之前的房间是一模一样,看来每个房间都是差不多的,而且房间5中也有一把钥匙;

     A,同样的,我会撕下一张空白的纸放进柜子localCycles中;

    

 

     B,我在我的本子上记录如下内容:

    

 

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;我使用房间5中的钥匙打开了东边的门

 

      D,我站在两个房间连接的过道上,发现下一个是房间6;

        我拿出我的本子,看看有没有这个房间6的相关信息:

     

 

    6,由于本子上并没有房间6的任何信息,所以我走进了房间6,并且房间6看起来和之前的房间是一模一样,并且有1把钥匙;

     A,同样的,我会撕下一张空白的纸放进柜子localCycles中;

      

 

     B,我在我的本子上记录如下内容:

    

 

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;我使用房间6中的钥匙打开了南边的门,因为房间6只有南边一扇门;

 

      D,我站在两个房间连接的过道上,发现下一个是房间7;

        我拿出我的本子,看看有没有这个房间7的相关信息:

    

 

    7,由于本子上并没有房间7的任何信息,所以我走进了房间7,并且房间7看起来和之前的房间是一模一样,并且有1把钥匙;

    A,同样的,我会撕下一张空白的纸放进柜子localCycles中;

      

 

     B,我在我的本子上记录如下内容:

    

 

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;我使用房间7中的钥匙打开了北边的门,因为房间7只有北边一扇门;

 

      D,我站在两个房间连接的过道上,发现下一个是房间5;

        我拿出我的本子,看看有没有这个房间5的相关信息:

     

 

    8,我发现本子上有房间5的信息;并且,房间5的状态还是在探索中的;

     这不就说明,在这条路线上出现了环路了吗;这个时候我就不能犯傻,一直开门、开门、开门往下走了,那必然会陷入无限的循环;

     如果觉得这个节点很重要可以这么记录:

     当然我的纸不够了,所以我记在脑子里,这个环路的起始节点是:房间5!

     我得赶紧原路返回(可以记在本子上,也可以记在脑子里,原路是什么顺序)了,于是我用房间7的钥匙打开了房间7,并在柜子localCycles记录如下内容:

    

 

    C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        发现并没有这样的门了,这种情况下我就:

 

      E,我又在我的笔记本上记录如下两项内容:(下图第二张图的最新内容来源于本房间柜子里的记录)

    

    

    F,我要原路返回了,我得带上房间7柜子里的纸片;

 

    9,我使用房间6的钥匙,回到了房间6中;

     我看看上个房间也就是房间7带回来的纸片,发现上面是这样的:

       我早就想好了,如果这张纸片不是空白的,我就会在当前房间的柜子里的纸片上记录如下内容:

    

 

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        发现并没有这样的门了,这种情况下我就:

 

       E,我又在我的笔记本上记录如下两项内容:(下图第二张图的最新内容来源于本房间柜子里的记录)

    

 

    F,我要原路返回了,我得带上房间6柜子里的纸片;

 

   10,返回房间5;

    我看看上个房间也就是房间6带回来的纸片,发现上面是这样的:

     同样的道理,如果这张纸片不是空白的,我就会在当前房间的柜子里的纸片上记录如下内容:

     

 

      C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        发现并没有这样的门了,这种情况下我就:

 

       E,我又在我的笔记本上记录如下两项内容:(下图第二张图的最新内容来源于本房间柜子里的记录)

    

 

    F,我要原路返回了,我得带上房间5柜子里的纸片;

 

   11,我用房间2的钥匙返回房间2;

    我看看上个房间也就是房间5带回来的纸片,发现上面是这样的:

 

    同样的道理,如果这张纸片不是空白的,我就会在当前房间的柜子里的纸片上记录如下内容:

     

 

     C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        我使用房间2的钥匙,打开了房间北边的门;

 

      D,我站在两个房间连接的过道上,发现下一个是房间4;

        我拿出我的本子,看看有没有这个房间4的相关信息:

     

 

    12,由于本子上并没有房间4的任何信息,所以我走进了房间4,并且房间4看起来和之前的房间是一模一样;

     A,同样的,我会撕下一张空白的纸放进柜子localCycles中;

      

 

    B, 我在我的本子上记录如下内容:

    

 

     C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        发现并没有这样的门了,这种情况下我就:

     

    E,我在我在我的本子上记录如下内容:

     

 

     F,我要原路返回了,我得带上房间4柜子里的纸片;

 

    13,我使用房间2的钥匙又回到了房间2中,我看看上个房间也就是房间4带回来的纸片,发现上面一片空白;

       同样的道理,如果这张纸片是空白的,我就在我随身携带的本子上记录如下内容:

    

 

     C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        发现并没有这样的门了,这种情况下我就:

 

      E,我又在我的笔记本上记录如下两项内容:(下图第二张图的最新内容来源于本房间柜子里的记录);

      我得先在本房间,也就是房间2,看下柜子里的纸片:

       所以两项内容是这样的:

    

 

     F,我要原路返回了,我得带上房间2柜子里的纸片;

 

    14,使用房间1的钥匙返回房间1

     我看看上个房间也就是房间2带回来的纸片,发现上面是这样的:;

 

     同样的道理,如果这张纸片不是空白的,我就会在当前房间的柜子里的纸片上记录如下内容:

    

 

       C,使用这个房间的钥匙去打开一扇未曾打开过的门;

        发现并没有这样的门了,这种情况下我就:

 

       E,我又在我的笔记本上记录如下两项内容:(下图第二张图的最新内容来源于本房间柜子里的记录);

    

 

    F,我要原路返回了,我得带上房间1柜子里的纸片;

      额,已经在原点了....

 

四,总结

    至此,从房间1的所有探所路径都已经探索结束了;是时候总结一下了:

    这个图说明了一条含有环路的路径;

      这个图好像被我搞砸了,只能说明某个没有环路的路径中包含这个表中的某个点。。。。。

 

五,拓展

  其实以上内容只是简单的模拟了:java程序中,虚拟机中栈帧的变化情况,以及栈帧之间的关系;

  涉及到栈帧的局部变量、堆的变量(是所有虚拟机栈(包括栈帧)共享的)、返回值的情况;最重要的就是虚拟机如何递归的过程。

 

六,未完待续

  下回有时间,可以将虚拟机栈(某个线程)、堆的示意图画出来。

 

 

     

 

    

posted @ 2020-07-03 18:01  seeAll  阅读(4035)  评论(0编辑  收藏  举报