1. 程式人生 > >搜尋_BFS(廣度優先搜尋)_演算法分析

搜尋_BFS(廣度優先搜尋)_演算法分析

    為方便討論BFS演算法, 考慮對圖的每個結點設定屬性color表示結點的顏色, color可取WHITE, GRAY, BLACK, 設定屬性d表示對應結點到源結點的最短路徑長度, 設定屬性p, 其中v.p表示存在一條從源結點到結點v的最短路徑且v的前驅為v.p, 下面先給出BFS演算法然後對其進行分析:

//以v為源點, 對圖G進行廣度優先遍歷 
BFS(G, s)
	for G中除s外每個結點v
		v.color = WHITE	
	s.color = GRAY
	s.d = 0
	s.p = NIL 
	建立初始僅包含結點s的佇列Q 
	while !Q.empty()
		u = Q.top()
		Q.pop()
		for 所有以u為起點的邊的終點v
			if v.color == WHITE
				v.color = GRAY
				v.d = u.d + 1
				Q.push(v)
		u.color = BLACK;	 

    結論1: G中從結點s可達的每個結點入佇列Q一次且出佇列Q一次

    證明: 根據每個節點入佇列Q之前為白色, 進入佇列後立即被設定為黑色可知每個結點至多入佇列一次和出佇列一次, 接下來證明G中從結點s可達每個結點均入佇列一次, 假設存在從結點s可達的結點a在演算法BFS執行的整個過程中未進入佇列Q, 記s到a的一條最短路徑為c_{1}...c_{k}, c_{1}=s, c_{k}=a, 那麼c_{k - 1}也應不進入佇列Q, 進而c_{k - 2}...c_{1}均不應進入佇列Q, 這顯然與第8行s進入佇列Q矛盾, 因此假設不成立, 故G中從結點s可達每個結點均入佇列一次.

    結論2: Q中始終包含G中所有被設定為灰色的結點, 設Q從隊頭到隊尾包含的元素為q_{1}...q_{n}

, 那麼q_{i - 1}.d <= q_{i}.d(1 <= 2 <= n), 且q_{n}.d <= q_{1}.d + 1

    證明: 考慮根據Q在各個時刻的狀態將時間分為若干個閉區間, 第i(i >= 0)個區間的起點對應Q的起始狀態為Q中只包含到源結點的最短路徑長度為i的結點且第i個區間終點對應Q中僅包含一個到源結點的最短路徑長度為i的結點, 使用數學歸納法較易證明結論2在每個時間區間均成立, 進而結論2是正確的, 此處不再贅述具體的證明過程.

    結論3: 演算法BFS執行完畢後, 設有向圖G{}'的結點集合為所有從源結點s可達的結點(包括源結點s), 其邊集為{<u, v> | v.p = v}, 那麼G{}'為一棵以s為根有向樹, 且G{}'

中任意結點u滿足: u.d等於s到u的最短路徑的距離, u.p對應該有向樹中u的父結點, 亦為某條從s到u的最短路徑上u的前驅結點.

    證明: 使用結論2證明過程中將時間分為多個區間的方法, 較易證明結論3的正確性, 此處不再贅述證明過程. 

    結論4: 演算法BFS的時間複雜度為O(v + e), 次數v為從結點s可達的結點個數, e為從結點s發出的所有路徑中不同邊的個數

    證明: 依據結論1和每個結點出佇列Q時第12行的for迴圈頭檢測將探索所有以u為起點的邊即可證明之.