廣度優先搜尋是一種用於圖的查詢演算法,它主要解決兩個問題:
1.從節點s到節點e有路徑嗎?
2.從節點s到節點e的所有路線中,哪條最短?
廣度優先搜尋的執行過程中,搜尋範圍從起點開始逐漸向外延伸,即先檢查一度關係,再檢查二度關係.
所謂一度關係:我的朋友和我就是一度關係.
所謂二度關係:我的朋友的朋友和我就是二度關係.
以此類推.
曾經不知道在**看到過一句話:
解決問題,先確定資料結構,資料結構確定好了,演算法自然而然就出來了.不過我覺得我離這個境界還有點遠....
那麼這個演算法應該用哪種資料結構來儲存資料呢?
因為乙個節點可以指向多個節點,當然,也可以不指向任何節點.所以我們可以用雜湊表: dictionary> (也許還有其他方式,但是小弟確實不懂,只懂這個)
由於多個節點可以指向同乙個節點,自己也可以指向自己,所以在搜尋的過程中,對於檢查過的節點,我們不能再去檢查,否則可能會導致無限迴圈,因此我們需要乙個資料結構來儲存搜尋過的節點,這個用 list或者 hashset都可以.
那麼這裡肯定需要一種資料結構來儲存需要檢查的節點.
同時,由於是從內到外,層層遞增搜尋,所有這裡就有個先後順序的問題了.那就是必須要把第一層的節點搜尋完,才能搜尋第2層,第2層的節點搜尋完,才能搜尋第3層.像這種有先後順序要求的資料結構,必須佇列:queue,我們將需要搜尋的節點放到佇列中,比如:
起點s的第1層關係中有2個節點:a和b,我們先把這兩個節點插入佇列.那麼這個插入有順序要求嗎?沒有!同一層的節點插入到佇列的順序不重要,因為該演算法計算的是最短距離,不是最快距離.
假設順序是a,b,我們先檢查a,如果a不是我們要找的終點(假設是e),那麼我們就把a指向的所有節點插入到佇列,插入到佇列後,它們是排在b的後面,所以只有等第1層的b檢查完了,才會檢查它們.當b檢查完了,也不是我們要找的終點,我們再把b指向的所有節點插入到佇列,這也就實現了1層1層的遞增檢查.
通過上面的方法,我們可以解決開篇提到的第1個問題:從s到e是否有路徑.但是無法解決第2個問題:最短路徑是哪條.
要解決這個問題,在搜尋的過程中就必須儲存當前搜尋的節點是從哪個節點過來的.因為前面也提到了,在圖這種資料結構中,多個節點是可以指向同乙個節點的.並且乙個節點也是可以指向多個節點的,所以我們必須清楚的知道,當前搜尋的節點是從哪個節點(哪條線路)過來的.
打個不太恰當的比方:
5+5=10
但是10!=5+5 ,10還可以==1+9,==2+8,==3+7 ......
所以,前面提到的,建立乙個佇列來儲存需要檢查的節點是不行的,我們還需要儲存節點的父節點,因為我們需要知道我們是怎麼來的!
因此,我封裝了一下當前節點型別,提供了乙個屬性來儲存它的父親.
(這個設計可能不太好,額外空間可能耗得比較多,小弟暫時沒想到什麼好的辦法)
**如下:
publicclass route
//////
完整路線
/// public
string fullroute
public route(stackstack)
}
publicclass routenode
public routenodeparent
public
routenode(t value)
public routeroute
route
route = new route(stack);
return
route;}}
}
publicclass mygraphwhere t : icomparable
public mygraph(dictionary>nodes)
public
void add(t key, ilistvalue)
//////
判斷是否有從 start 到 end 的路徑
/// ///
開始點 ///
結束點 ///
路線 ///
public
bool tryfindminroute(t start, t end, out routeroute)
if (nodes == null || nodes.count == 0
)
//已搜尋元素的集合
var searched = new hashset();
//將要搜尋的節點佇列
var searching = new queue>();
foreach (var item in
nodes));}
while (searching.count > 0
)
if (node.value.compareto(end) == 0
)
searched.add(node.value);
if (_nodes.trygetvalue(node.value, out
var forwardnodes) == false || forwardnodes == null || forwardnodes.count == 0
)
foreach (var item in forwardnodes.where(item => searched.contains(item) == false
)) );}}
return
false
; }
}
test:
mygraph dic = new mygraph();dic.add(
"start
", new list );
dic.add(
"bob
", new list );
dic.add(
"alice
", new list );
dic.add(
"claire
", new list );
dic.add(
"anuj
", new list() );
dic.add(
"dandan2
", new list() );
dic.add(
"peggy
", new list() );
dic.add(
"gongwei
", new list() );
dic.add(
"thom
", new list());
dic.add(
"jonny
", new list );
dic.add(
"wjire
", new list());
dic.add(
"refuge
", new list() );
var r = dic.tryfindminroute("
alice
", "
claire
", out
varroute);
if(r)
層找到:
" +route.fullroute);
}else
搜尋 廣度優先搜尋
廣度優先搜尋一層一層地進行遍歷,每層遍歷都是以上一層遍歷的結果作為起點,遍歷乙個距離能訪問到的所有節點。需要注意的是,遍歷過的節點不能再次被遍歷。class solution,int shortestpathbinarymatrix vectorint grid length return 1 cl...
廣度優先搜尋
include include include include using namespace std struct node 圖頂點結構定義 typedef struct node graph 圖形的結構新型態 struct node head 9 圖形頂點陣列 int visited 9 遍歷標...
廣度優先搜尋
廣度優先搜尋詳解 1.也稱寬度優先搜尋,顧名思義,就是將一棵樹一層一層往下搜。演算法首先搜尋和s距離為k的所有頂點,然後再去搜尋和s距離為k l的其他頂點。bfs是一種完備策略,即只要問題有解,它就一定可以找到解。並且,廣度優先搜尋找到的解,還一定是路徑最短的解。但是它盲目性較大,尤其是當目標節點距...