有向圖的深度優先搜索 —— 找出環路


一、目標

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

  

 

二、策略

  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程序中,虛擬機中棧幀的變化情況,以及棧幀之間的關系;

  涉及到棧幀的局部變量、堆的變量(是所有虛擬機棧(包括棧幀)共享的)、返回值的情況;最重要的就是虛擬機如何遞歸的過程。

 

六,未完待續

  下回有時間,可以將虛擬機棧(某個線程)、堆的示意圖畫出來。

 

 

     

 

    


免責聲明!

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



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