1. 程式人生 > >資料結構——圖(6)——深入分析BFS演算法

資料結構——圖(6)——深入分析BFS演算法

DFS的不足和BFS演算法

雖然我們知道根據DFS演算法我們可以找到所有的,由起始節點到目標節點的所有路徑,但並不代表那條路是最短的或者是最佳的。就像我們上篇文章所說的一樣,對於同一幅圖,非遞迴演算法找到的路徑就明顯比遞迴演算法找的要短。
回顧我們之前提到的BFS的基本思想:從起始頂點開始,首先探索鄰居節點,然後再移動到下一級鄰居。
在這裡插入圖片描述
假設我們從a走到i,按照BFS演算法,應該是
a -> d-> h ->i (並且這是一條最短的路徑
其BFS虛擬碼如下:

bfs from v1 to v2:
	//建立一個佇列q來儲存走過的路徑path(可以用vector來儲存路徑)
    create a queue of paths (a vector), q
    //將節點v1的路徑入隊
    q.enqueue(v1 path)
    //當q不為空,並且節點V2未被訪問時
    while q is not empty and v2 is not yet visited:
    //將q中的元素移出佇列,並且存入path中
        path = q.dequeue()
        //將路徑中的最後元素賦值給節點型變數v
        v = last element in path
        //如果v未被訪問
        if v is not visited:
        //標記節點V
        mark v as visited
        //如果節點是目標節點,停止執行
        if v is the end vertex, we can stop.
        //遍歷V中所有未被標記的鄰居
        for each unvisited neighbor of v:
        //將v節點的鄰居作為最後的元素構成新的路徑
             make new path with v's neighbor as last element
             //將新的路徑排入佇列中
             enqueue new path onto q 


沒錯 這是一個很複雜的步驟。理解都有點困難更別提記住了,但是我們可以注意到,這個實現過程跟DFS的非遞迴實現是非常類似的。下面我們也是同樣的分析一下實現過程:
還是從a到i,front指標指向隊頭。

  1. 先建立一個vector,用來儲存路徑,建立一個佇列將路徑裝入:
Vector<Vertex  *> startPath
	startPath.add(a)
	q.enqueue(startPath)
  1. 此時佇列中有元素a,已經訪問的集合為空:
    在這裡插入圖片描述
    在這裡插入圖片描述
  2. 接下來到達迴圈語句:
in while loop:
   //將佇列中的元素取出,放到當前路徑的變數中
   curPath = q.dequeue() (path is a)
   //由於佇列中只有一個元素a,所以它的最後元素也是它本身
   v = last element in curPath (v is a)
   //標記V
   mark v as visited
   //將所有的未標記的路徑入隊q中
   enqueue all unvisited neighbor paths onto q

這裡注意,這裡最後一句入隊的是路徑而不是節點,標記的才是及誒單。執行完畢後,佇列跟訪問集的情況如下:
在這裡插入圖片描述
在這裡插入圖片描述

  1. 此時佇列不為空,直接從while迴圈開始。
in while loop:
   curPath = q.dequeue() (path is ab)
   v = last element in curPath (v is b)
   mark v as visited
   enqueue all unvisited neighbor paths onto q


根據佇列的性質,FILO,所以最先出佇列的是ab,ab路徑中最後的元素是b,所以,標記b,並將b的所有鄰居放入佇列中去:
在這裡插入圖片描述


在這裡插入圖片描述

5.重複上述過程,直到路徑中的最後的元素為目標元素 i 時,停止搜尋。此時情況如下:

in while loop:
   curPath = q.dequeue() (path is adhi)
   v = last element in curPath (v is i)
   found!

在這裡插入圖片描述
在這裡插入圖片描述在這裡插入圖片描述
此時的路徑 a -> d-> h ->i 也是最短的路徑

總結

在對於需要找到最短路徑的圖來說,BFS是絕佳的選擇。廣度優先搜尋將查詢從起始節點可到達的所有節點。
●它將按距離遞增的順序訪問它們。
●在n節點m邊圖中,需要時間O(m + n)並使用空間O(n)。
●但在實踐中,空間使用率遠高於DFS。

這裡有個有趣的問題,如果我們將BFS思想運用在樹的遍歷中會得到什麼結論?得到一種我們熟悉的遍歷方式。樹中可是沒有環的。