這幾篇將主要根據我們之前所學的圖的遍歷演算法來解決一些問題,下面我們來看這樣的乙個問題。
問題:求不帶權連通圖g中從頂點u到頂點v的一條最短路徑。(即求頂點u到頂點v之間邊數最少的頂點序列)。
圖1-求最短路徑
例如,對於這樣的乙個有向圖,我們要求頂點0到頂點7的最短路徑。對於求最短路徑,我們是選擇dfs還是bfs呢?這是乙個值得思考的問題。
首先來看dfs深度優先搜尋:
圖2-dfs深度優先搜尋
如果採用dfs深度優先搜尋的話,得到的路徑可能是0 - 1 - 3 - 6 - 7這樣的路徑,而根據之前我們學習dfs深度優先搜尋過程可知,簡單來說,dfs深度優先搜尋就是選擇乙個方向(頂點),然後依次訪問下去(訪問鄰接點)
,直到訪問到終點為止,在這個過程中dfs深度優先搜尋並不關心這是否是一條最短路徑
,而從最終搜尋到的路徑來看,這顯然不是一條最短路徑。
我們再來看bfs廣度優先搜尋:
圖3-bfs廣度優先搜尋
從圖3來看,bfs廣度優先搜尋是對每一層的所有相鄰的頂點進行搜尋,直到找到終點為止。在這個搜尋過程中,廣度優先搜尋會對所有的鄰接點進行了訪問
,因此當廣度優先搜尋完成後,我們就可以知道有這樣的一條最短路徑可以到達頂點v(即序列:0 - 2 - 5 - 7)。
1. 從頂點u出發一層一層地向外擴充套件
2. 利用佇列記錄訪問的順序
3. 當第一次找到頂點v時佇列中便包含了最短路徑,同時在搜尋過程中利用佇列儲存最短路徑(這是乙個普通佇列,而非之前所說的環形佇列)
4. 然後再利用佇列輸出最短路徑(逆路徑)
如果你還是有些疑惑的話(比如逆路徑),不要急,接下來我們還會繼續介紹。最好是先把bfs演算法先熟悉一下,有助於理解這個求最短逆路徑演算法,求最短逆路徑演算法的實現:
//求最短逆路徑演算法
void shortpath(algraph *g,int u,int v)
printf("%2d\n",qu[i].data);
break;
}//訪問w的所有鄰接點(這一步操作非常重要,體現bfs廣度優先搜尋,相信大家對這一步操作已經不陌生了吧)
圖4-求最短路徑演算法的過程
還記得前面我們說過的逆路徑
嗎?求最短逆路徑演算法過程如圖4所示,bfs廣度優先搜尋會將所有搜尋到的頂點進行入隊,每個頂點入隊時會記錄兩項資訊,其中data域記錄頂點的資訊,parent域記錄上乙個頂點的下標位置。比如對於頂點5來說,data會記錄頂點5的值,而parent域會記錄頂點5的上乙個頂點2的下標位置(下標為2)。這樣我們就可以通過這種方式輸出逆路徑了。
而求最短逆路徑演算法中的頂點w則會記錄每個出隊的頂點,所以當頂點w為頂點7時,此時頂點w和頂點v相等,則說明找到了最短逆路徑,所以會從頂點7開始輸出,並根據頂點7的parent域找到上乙個頂點,並輸出頂點5,以此類推,直到頂點的parent為-1,這說明逆路徑就輸出完畢了。
BFS求最短路
假設有乙個n行m列的迷宮,每個單位要麼是空地 用1表示 要麼是障礙物 用0表示 如和找到從起點到終點的最短路徑?利用bfs搜尋,逐步計算出每個節點到起點的最短距離,以及最短路徑每個節點的前乙個節點。最終將生成一顆以起點為根的bfs樹。此時bfs可以求出任意一點到起點的距離。poj3984 bfs求最...
BFS求最短路
假設有乙個n行m列的迷宮,每個單位格要麼是空地 用1來表示 要麼是障礙物 用0來表示 如何找到從起點到終點的最短路徑?分析 要找到終點到起點的最短路徑,可以使用二叉樹的bfs,因為二叉樹的bfs的訪問順序就是結點到根節點的距離,從小到大訪問的,因此可以從迷宮圖的起點開始進行bfs的寬度優先遍歷。遍歷...
最短路 求最長最短路,求最短路的路徑
hdu 1595 find the longest of the shortest include include include include include include include include include include include include include defi...