深度優先搜索(DFS) 深度優先搜索在搜索過程中訪問某個頂點后,需要遞歸地訪問此頂點的所有未訪問過的相鄰頂點。 初始條件下所有節點為白色,選擇一個作為起始頂點,按照如下步驟遍歷: a. 選擇起始頂點塗成灰色,表示還未訪問 b. 從該頂點的鄰接頂點中選擇一個,繼續這個過程(即再尋找鄰接結點的鄰接結點),一直深入下去,直到一個頂點沒有鄰接結點了,塗黑它,表示訪問過了 c. 回溯到這個塗黑頂點的上一層頂點,再找這個上一層頂點的其余鄰接結點,繼續如上操作,如果所有鄰接結點往下都訪問過了,就把自己塗黑,再回溯到更上一層。 d. 上一層繼續做如上操作,知道所有頂點都訪問過。 用圖可以更清楚的表達這個過程:
1.初始狀態,從頂點1開始
2.依次訪問過頂點1,2,3后,終止於頂點3
3.從頂點3回溯到頂點2,繼續訪問頂點5,並且終止於頂點5
4.從頂點5回溯到頂點2,並且終止於頂點2
5.從頂點2回溯到頂點1,並終止於頂點1
6.從頂點4開始訪問,並終止於頂點4
從頂點1開始做深度搜索:
- 初始狀態,從頂點1開始
- 依次訪問過頂點1,2,3后,終止於頂點3
- 從頂點3回溯到頂點2,繼續訪問頂點5,並且終止於頂點5
- 從頂點5回溯到頂點2,並且終止於頂點2
- 從頂點2回溯到頂點1,並終止於頂點1
- 從頂點4開始訪問,並終止於頂點4
演示深度優先搜索的過程
還是引用上篇文章的樣例圖,起點仍然是V0,我們修改一下題目意思,只需要讓你找出一條V0到V6的道路,而無需最短路。


假設按照以下的順序來搜索:
1.V0->V1->V4,此時到底盡頭,仍然到不了V6,於是原路返回到V1去搜索其他路徑;
2.返回到V1后既搜索V2,於是搜索路徑是V0->V1->V2->V6,,找到目標節點,返回有解。
3.1.舉例
給出如圖3-1所示的圖,求圖中的V0出發,是否存在一條路徑長度為4的搜索路徑。



圖3-1
顯然,我們知道是有這樣一個解的:V0->V3->V5->V6。
3.2.處理過程





















3.3.對應例子的偽代碼
這里先給出上邊處理過程的對應偽代碼。
Cpp代碼
- /**
- * DFS核心偽代碼
- * 前置條件是visit數組全部設置成false
- * @param n 當前開始搜索的節點
- * @param d 當前到達的深度,也即是路徑長度
- * @return 是否有解
- */
- bool DFS(Node n, int d){
- if (d == 4){//路徑長度為返回true,表示此次搜索有解
- return true;
- }
- for (Node nextNode in n){//遍歷跟節點n相鄰的節點nextNode,
- if (!visit[nextNode]){//未訪問過的節點才能繼續搜索
- //例如搜索到V1了,那么V1要設置成已訪問
- visit[nextNode] = true;
- //接下來要從V1開始繼續訪問了,路徑長度當然要加
- if (DFS(nextNode, d+1)){//如果搜索出有解
- //例如到了V6,找到解了,你必須一層一層遞歸的告訴上層已經找到解
- return true;
- }
- //重新設置成未訪問,因為它有可能出現在下一次搜索的別的路徑中
- visit[nextNode] = false;
- }
- //到這里,發現本次搜索還沒找到解,那就要從當前節點的下一個節點開始搜索。
- }
- return false;//本次搜索無解
- }
3.4.DFS函數的調用堆棧

此后堆棧調用返回到V0那一層,因為V1那一層也找不到跟V1的相鄰未訪問節點

此后堆棧調用返回到V3那一層

此后堆棧調用返回到主函數調用DFS(V0,0)的地方,因為已經找到解,無需再從別的節點去搜別的路徑了。
DFS 算法
思想:一直往深處走,直到找到解或者走不下去為止

BFS算法

DFS:使用棧保存未被檢測的結點,結點按照深度優先的次序被訪問並依次被壓入棧中,並以相反的次序出棧進行新的檢測。

BFS:使用隊列保存未被檢測的結點。結點按照寬度優先的次序被訪問和進出隊列。
