搜索是常見的解決問題的方法,常見的搜索方式有深度優先搜搜和廣度優先搜索,一般來說都是搜索只不過方式略有不同,所以我之前在學習搜索的時候一直都是練習的深度優先搜索,也很少有哪些問題就必須用深度優先或者廣度優先,否則就解不出來的,基本上會一種我感覺也差不多,但是呢,有的問題他還是最好用相應的解法效率更高一些,所以就來補補廣度優先搜索。
【廣度優先搜索(BFS)】
廣度優先搜索BFS(Breadth First Search)也稱爲寬度優先搜索,它是一種先生成的結點先擴展的策略。
BFS的思想有點像樹的遍歷當中的層序遍歷,一層一層的搜索,搜索完一層後再搜下一層,直到最後得到想要的結果。
在廣度優先搜索算法中,解答樹上結點的擴展是按它們在樹中的層次進行的。首先生成第一層結點,同時檢查目標結點是否在所生成的結點中,如果不在,則將所有的第一層結點逐一擴展,得到第二層結點,並檢查第二層結點是否包含目標結點,……,對層次爲n+1的任一結點進行擴展之前,必須先考慮層次完層次爲n的結點的每種可能的狀態。因此,對於同一層結點來說,求解問題的價值是相同的,可以按任意順序來擴展它們。通常採用的原則是先生成的結點先擴展。
參考
【什麼時候用BFS比較好?】
簡單點來說是廣度優先搜索適用於只需要求出最優解的問題。至於爲什麼呢?
我覺得深度優先搜索特別適用於統計路徑的條數,比如說走迷宮的問題,一共有多少條路徑能夠到達出口這種問題,很適合用dfs來解決,如果要找最佳路徑,也只能找出所有的路徑之後來比較得出最優解。
那麼如果是用BFS呢?
【BFS的實現】
首先要一個表來存儲所有的節點,因爲BFS是先生成的節點先擴展,類似於數據結構中的隊列(先進先出),所以一般是用一個數組模擬隊列的結構,front和rear分別表示頭和尾指針,初始狀態是rear=front,rear++表示入隊,front++表示出隊。
廣度優先搜索算法的搜索步驟一般是:
(1)從隊列頭取出一個結點,檢查它按照擴展規則是否能夠擴展,如果能則產生一個新結點。
(2)檢查新生成的結點,看它是否已在隊列中存在,如果新結點已經在隊列中出現過,就放棄這個結點,然後回到第(1)步。否則,如果新結點未曾在隊列中出現過,則將它加入到隊列尾。
(3)檢查新結點是否目標結點。如果新結點是目標結點,則搜索成功,程序結束;若新結點不是目標結點,則回到第(1)步,再從隊列頭取出結點進行擴展。
廣度優先搜索中問題不同具體的策略是不同的但是,答題的框架的類似的,但看下面這個實在是看不太懂,做幾道題來深入理解一下就好了。
void BFS(){
隊列初始化;
初始結點入隊;
while (隊列非空) {
隊頭元素出隊,賦給current;
while (current 還可以擴展){
由結點current擴展出新結點new;
if (new 重複於已有的結點狀態) continue;
new結點入隊;
if (new結點是目標狀態){
置flag= true;
break;
}
}
}
}