1. 程式人生 > >資料結構——圖(4)——廣度優先搜尋(BFS)演算法思想

資料結構——圖(4)——廣度優先搜尋(BFS)演算法思想

廣度優先搜尋

儘管深度優先搜尋具有許多重要用途,但該策略也具有不適合某些應用程式的缺點。 深度優先方法的最大問題在於它從其中一個鄰居出發,在它返回該節點或者是訪問其他鄰居之前,它必須訪問完從出發節點開始的整個路徑。 如果我們嘗試在一個大的圖中發現兩個節點之間的最短路徑,則使用深度優先搜尋會將我們一直帶到圖的遠端,即使我們的的目的地離我們的出發點僅有一步之遙。
廣度優先搜尋(Breadth-first search BFS)演算法通過按照與起始節點的接近程度來確定該訪問哪個節點 來解決該問題,該節點根據沿最短可能路徑的弧的數量來測量。 通過計算弧來測量距離時,每個弧構成一跳(hop

)。 因此,廣度優先搜尋的本質是首先訪問起始節點,然後是一跳之外的節點,然後是節點兩跳,依此類推。

BFS過程分析

我們還是用上次的圖來說明一下我們的BFS演算法,並且與DFS做一個比較。

  1. 第一步是一樣的,我們得選一個起始節點,所以我們選擇與BFS演算法一致的起點:
    在這裡插入圖片描述
  2. 下一階段訪問與該節點距離一跳的節點,圖中我們容易看出是Dallas,Denver還有Portland三個節點:
    在這裡插入圖片描述
  3. 至此我們繼續探索跳數為2的節點,如下:
    在這裡插入圖片描述
  4. 最終,我們就這樣遍歷完了圖中所有的節點在這裡插入圖片描述

實現廣度優先演算法的最簡單方法是使用佇列用來存放未處理的節點。 在該過程的每個步驟中,我們將當前節點的鄰居排入佇列。 因為佇列是按順序處理的,所以距離起始節點一跳的所有節點將比兩跳的節點在佇列中更早出現。

/*
* 函式: breadthFirstSearch
* 用法: breadthFirstSearch(node);
* --------------------------------
* 從指定的節點處進行廣度優先搜尋.
*/
void breadthFirstSearch(Node *node) {
	Set<Node *> visited; //標記已訪問的節點
	Queue<Node *> queue;//建立儲存未被處理的節點
	queue.enqueue(node); //將要處理的節點放入空佇列中
	while (!queue.isEmpty()) {//當佇列中的節點數不為空時
		node = queue.dequeue(); //將佇列中的節點從佇列中移出
		if (!visited.contains(node)) {//如果該節點未被標記
			visit(node);//對節點進行相應處理
			visited.add(node);//處理完畢後標記該節點
			 //遍歷該節點指向的下一條弧
			foreach (Arc *arc in node->arcs) {
			//將該弧所指的節點放入佇列中
				queue.enqueue(arc->finish);
			}
		}
	}
}

同樣的,利用這樣的做法我們可以利用BFS來遍歷下圖:
在這裡插入圖片描述
具體的實現跟步驟分析下篇博文會進行說明。