DFS(深度優先遍歷) & BFS:(廣度優先遍歷)

 

DFS (Deep First Search)

概念:

    顧名思義,這種遍歷方法是以深度爲優先進行對圖的搜索或者遍歷,至於什麼是以深度爲優先條件,先看下面DFS的基本步驟:

   ( 這是一個遞歸思想的DFS)

    DFS:從當前節點開始,先標記當前節點,再尋找與當前節點相鄰,且未標記過的節點:

        (1): 當前節點不存在下一個節點,則返回前一個節點進行DFS

        (2): 當前節點存在下一個節點,則從下一個節點進行DFS

   下面是圖解:

    一開始,可以看出,若沒有走到死路,這種遍歷方式會從start節點沿着一條路一直深入下去(start -> 1 -> 2 -> 3。

   

    若走到死路,便會退回上一節點,遍歷上一節點的其他相鄰節點(2 -> 4)。

     

    這樣一直重複,直到找到終點。

     

    所以跟你所見到的一樣,這樣的搜索方法像一根貪婪的蚯蚓,喜歡往深的地方鑽,所以就自然而然的叫做深度優先算法了。其用途也是非常多的,我覺得最直觀的用法之一是用來尋找迷宮的出口 。

   我們可以順勢寫出DFS的僞代碼:

        find(節點){

            if(此結點已經遍歷 || 此節點在圖外 || 節點不滿足要求) return;

            if(找到了end節點) 輸出結果 ; return;

            標記此節點,表示已經遍歷過了;

            while(存在下一個相鄰節點) find(下一個節點);

        }

 

BFS (Breadth First Search)

概念:

    對於深度優先算法,強迫症就很不爽了,並表示:“爲什麼不乾乾淨淨,一層一層地從start節點搜索下去呢,就像病毒感染一樣,這樣纔像正常的搜索的樣子嘛。”於是便有了BFS算法(誤)。廣度優先算法便如其名字,它是以廣度爲優先的,一層一層搜索下去的,就像病毒感染,擴散性的傳播下去。

    圖解:

    下圖中,start爲搜索的初始節點,end爲目標節點

                       

   我們先把star節點的關聯節點遍歷一次

                       

    接下來把第一步遍歷過的節點當成start,重複第一步

                      

    重複一二步,這樣便是一個放射樣式的搜哦防範,直到找到end節點

                      

    可以看出,這樣放射性的尋找方式,能找到從start到end的最近路(因爲每次只走一步,且把所有的可能都走了,誰先到end說

    明這就是最短路)。但這樣如何用代碼實現?用棧貌似不行,改變遞歸的順序也不行。

    這裏需要用到隊列

    a.比如每遍歷start周圍的一個“1”節點的時候,就把跟它相關聯的“2”節點保存到隊列中(“1”節點訪問完之後隊列內容:2,2,2,2)

    b.然後依次訪問隊列內容,並對每個隊列元素重複a步驟(訪問一個“2”節點之後隊列的內容:2,2,2,3,3)。

    c.由此重複下去,直到隊列爲空或者搜索到終點。

    廣度優先的[遞歸]僞代碼如下:

        把start節點push入隊列;

        while(隊列不爲空) {

            把隊列首節點pop出隊列;

            對節點進行相關處理或者判斷;

            while(此節點有下一個相關節點){

                把相關節點push入對列;

            }

        }

    應用例題:Abbott的復仇(Abbott's Revenge, ACM/ICPC World Finals 2000, UVa 816)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章