【圖論】廣度優先搜索和深度優先搜索
寫在最前面的
兩種圖的遍歷算法在其他圖的算法當中都有應用,並且是基本的圖論算法。
廣度優先搜索
廣度優先搜索(BFS),可以被形象的描述爲“淺嘗輒止”,具體一點就是每個頂點只訪問它的鄰接節點(如果它的鄰接節點沒有被訪問)並且記錄這個鄰接節點,當訪問完它的鄰接節點之後就結束這個頂點的訪問。
廣度優先用到了“先進先出”隊列,通過這個隊列來存儲第一次發現的節點,以便下一次的處理;而對於再次發現的節點,我們不予理會——不放入隊列,因爲再次發現的節點:
- 無非是已經處理完的了;
- 或者是存儲在隊列中尚未處理的。
《算法導輪》對兩種搜索都採用了很聰明的做法,用白色WHITE來標誌未發現的節點,用灰色GRAY來標誌第一次被發現的節點,用黑色BLACK來標誌第二次被發現的節點。
於是有了:
導輪還在上面僞代碼的“其他”中加入了訪問長度和父節點的操作。此舉可以算出,從源點到其他頂點路徑的最少步數和它的具體路徑。
關於廣度優先搜索的一個簡單應用:
假如有問題,每個村莊之間都通過橋來聯通,先給出村莊的圖,問村莊A到村莊B最少要通過多少座橋?這個問題可以很容易的轉化爲上面的BFS問題。
深度優先搜索
深度優先搜索(DFS),可以被形象的描述爲“打破沙鍋問到底”,具體一點就是訪問一個頂點之後,我繼而訪問它的下一個鄰接的頂點,如此往復,直到當前頂點一被訪問或者它不存在鄰接的頂點。
同樣,算法導論採用了“聰明的做法”,用三種顏色來標記三種狀態。但這三種狀態不同於廣度優先搜索:
- WHITE 未訪問頂點
- GRAY 一條深度搜索路徑上的頂點,即被發現時
- BLACK 此頂點的鄰接頂點被全部訪問完之後——結束訪問次頂點
通過給DFS搜索過程中給每一個頂點加時間戳,就可以實現拓撲排序了。實現拓撲排序需要:
對於每一個頂點,都有兩個時間戳,分別這樣來定義:
- 在一頂點剛被發現的時候,標記此頂點的第一個時間戳;
- 在結束此頂點的訪問的時候,標記此頂點的第二個時間戳。時間戳可以用簡單的123456來標記,只要能區分大小就行。
總結
兩個算法都是O(V+E),在用到的時候適當選取。在使用白灰黑標誌的時候,突然明白瞭如何用深度優先搜索來判斷有向圖中是否存在環。
深度優先和廣度優先各有各的優缺點:
- 廣優的話,佔內存多,能找到最優解,必須遍歷所有分枝. 廣優的一個應用就是迪科斯徹單元最短路徑算法.
- 深優的話,佔內存少,能找到最優解(一定條件下),但能很快找到接近解(優點),可能不必遍歷所有分枝(也就是速度快), 深優的一個應用就是連連看遊戲.
在更多的情況下,深優是比較好的方案。
本文完 2012-05-16