算法圖解之廣度優先搜索


廣度優先搜索的應用場景,如下:
(1)編寫國際跳棋AI,計算最少走多少步就可獲勝;
(2)編寫拼寫檢查器,計算最少編輯多個地方就可將錯拼的單詞改為正確的單詞,如將READED改為READER需要編輯一個地方;
(3)根據你的人際關系網絡找到關系最近的醫生;

圖簡介

假設你居住在舊金山,要從雙子峰前往金門大橋。你想乘公交車前往,並希望換乘最少。可乘坐的公交車如下:

由圖可知,換乘最少的路線是:步行->44路公交車->28路公交車(一共三步,這種問題也被稱作為最短路徑問題,解決最短路徑問題的算法,又稱廣度優先搜索)

要確定如何從雙子峰前往金門大橋,需要兩個步驟:
(1)使用圖來建立問題模型;
(2)使用廣度優先搜索解決問題;

什么是圖

圖模擬一組連接。

例如,假設你與朋友玩牌,並要模擬誰欠誰錢,可像下面這樣指出Alex欠Rama前,如圖:

完整的欠錢圖可能類似於下面這樣。

Alex欠Rama錢、Tom欠Adit錢,等等。

圖由節點和邊組成,如圖所示:

一個節點可能與眾多節點直接相連,這些節點被稱為鄰居。
在起前面的欠錢圖中,Rama是Alex的鄰居。Adit不是Alex的鄰居,因為他們不直接相連。但Adit既是Rama的鄰居,又是Tom的鄰居。

圖用於模擬不同的東西是如何相連的。

聯系工程研發:
通常研發工程師面對業務需求,需要畫流程圖幫助自己梳理一下業務流程,減少編碼過程中的不必要的錯誤(這個不必要主要包含業務理解等)。
業務流程圖其實也相當於在模擬業務在實際中是如何運作的。

廣度優先搜索

廣度優先搜索是一種用於圖的查找算法,可幫助回答兩類問題:

  • 第一類問題:從節點A出發,前往節點B的路徑
  • 第二類問題:從節點A出發,前往節點B的哪條路徑最短

查找最短路徑問題

這個圖主要反映的是解決第一類問題看你周圍的朋友有哪些是芒果商。

第二類問題,主要強調是是哪個芒果商與你的關系最近。例如,朋友是一度關系,朋友的朋友是二度關系。

下圖可形象生動的表現出來:

搜索范圍從起點開始逐漸向外延伸,即先檢查一度關系,再檢查二度關系。
首先按照順序檢查名單中的每個人,看看他是否是芒果銷售商。這將在一度關系種查找,再在二度關系中查找,因此找到的是關系最近的芒果銷售商。廣度優先搜索不僅查找從A到B的路徑,而且找到的是最短的路徑。

如圖分析:

注意,只有按添加順序查找時,才能實現這樣的目的。換句話說,如果Claire先於Anuj加入名單,就需要先檢查Claire,再檢查Anuj。如果Claire和Anuj都是芒果銷售商,而你先檢查Anuj再檢查Claire,結果將如何呢?找到的芒果銷售商並非是與你關系最近的,因為Anuj是你朋友的朋友,而Claire是你的朋友。因此,你需要按添加順序進行檢查。有一個可實現這種目的的數據結構,那就是隊列。

隊列

隊列的工作原理與現實生活中的隊列完全相同。

假設你與朋友一起在公交車站排隊,如果你排在他的前面,你將先上車。隊列的工作原理與此相同。隊列類似於棧。你不能隨機地訪問隊列中的元素。隊列只支持兩種操作:入隊和出隊。

如果你將兩個元素加入隊列,先加入的元素將在后加入的元素之前出隊。因此,你可使用隊列來表示查找名單。這樣,先加入的人將先出隊並先被檢查。 隊列是一種先進先出的數據結構,而棧是一種后進先出的數據結構,如圖:

實現圖

圖由多個節點組成。

每個節點都與鄰近節點相連,如果表示類似於”you->Bob”這樣的關系,可以使用散列表。

關於有向圖和無向圖,如下所示:

關於運行時間:
如果你在你的整個人際關系網中搜索芒果銷售商,就意味着你將沿每條邊前行(記住,邊是從一個人到另外一個人的箭頭或連接),因此運行時間至少為O(邊數)

你還使用了一個隊列,其中包含要檢查的每個人。將一個人添加到隊列需要的時間是固定的,即為O(1),因此對每個人都這樣做需要的總時間為O(人數)。所以,廣度優先搜索的運行時間為O(人數+邊數),這通常寫作O(V+E),其中V為頂點數,E為邊數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM