0演算法基礎學演算法 搜尋篇第二講 BFS廣度優先搜尋的思想

球君發表於2021-06-14

  dfs前置知識:

    遞迴連結:0基礎演算法基礎學演算法 第六彈 遞迴 - 球君 - 部落格園 (cnblogs.com)

    dfs深度優先搜尋:0基礎學演算法 搜尋篇第一講 深度優先搜尋 - 球君 - 部落格園 (cnblogs.com)

  本講前置知識:

    佇列:0基礎學演算法 第三彈 佇列 - 球君 - 部落格園 (cnblogs.com)    

    ↑早期作品,慎用↑

  我們在上一講稍微說了一下關於深度優先搜尋的常識,今天我們的主題是廣度優先搜尋

  廣度優先搜尋,簡稱BFS,同dfs一樣,屬於十分常見的演算法,也是最常用的搜尋方法之一,由於思路和dfs完全不同,這也導致了它們在性質和作用上的不同,接下來,我們來結合上一講的部分例子,說一說廣度優先搜尋的順序與使用方法。

還記得這張圖嗎(2020/11/1的產物)

一、BFS的演算法思想

  在dfs中,由於我們會選擇從原始節點沿一條搜尋路線找到底部的節點,再從底部節點回溯到上一個節點繼續看有沒有更多可能,這書使用了遞迴

  在bfs中,我們會在初始節點處開始往下尋找,找到它的所有子目錄節點,再尋找它子目錄下的所有子目錄節點,從此達成遍歷,請看以下過程

 第一步要確定搜尋起點,即原始節點,從這裡開始搜尋

 

從①往下找自然可以找到②

 

 

從①往下還可以找到⑩

 

目前我們對這張圖的遍歷順序:①→②→⑩→③→⑦→⑧

 

搜尋順序追蹤:①→②→⑩→③→⑦→⑧→④→⑤→⑨

 

  最後從⑤找到了⑥,由於再也找不到任何一個了,此時所有節點都以找到,搜尋結束

  一般來講,dfs會使用到遞迴,而bfs不需要,這和它的中心思想有關,dfs需要不斷挖深,挖到底還需要往上爬,但根據剛剛bfs的搜尋順序圖,不難看出bfs在到底後搜尋就結束了,所以說bfs不需要用到遞迴,只需要用到普通的迴圈。

  但是,怎樣才能做到依次載入一個節點的每一個子節點,然後繼續依次載入它的子節點的子節點呢?

二、佇列實現BFS

  佇列是實現BFS最常用的方法,我個人比較喜歡使用c++標準模板庫STL中的“佇列”queue(stl佇列介紹:見篇首)不過使用手打的佇列也無傷大雅。

  總的來說,原理就是載入初始節點,再將它的子節點全部載入,彈出他,從第一個子節點開始,載入子節點的子節點們,彈出子節點……

  舉了例子,有如下圖

 

  那麼我們使用BFS時,佇列裡是什麼情況呢

 

 

建立佇列後壓入頭節點

壓入頭節點的子節點

 

 

彈出頭節點

 

 

壓入第一個子節點的所有子節點

 

 

如圖

  接下來重複以上操作,直到佇列彈空

  由於接下來的③⑦⑧⑤⑥均沒有子節點了,所以搜尋結束,所有節點完成遍歷。

  本期的內容差不多到這裡就結束了,關於程式碼實現的問題,敬請期待下一期BFS廣度優先搜尋的實現與實踐,記得點贊關注!

 

相關文章