C 廣度優先搜尋

2022-01-11 07:44:25 字數 3741 閱讀 2622

廣度優先搜尋是一種用於圖的查詢演算法,它主要解決兩個問題:

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 ......

所以,前面提到的,建立乙個佇列來儲存需要檢查的節點是不行的,我們還需要儲存節點的父節點,因為我們需要知道我們是怎麼來的!

因此,我封裝了一下當前節點型別,提供了乙個屬性來儲存它的父親.

(這個設計可能不太好,額外空間可能耗得比較多,小弟暫時沒想到什麼好的辦法)

**如下:

public

class route

//////

完整路線

/// public

string fullroute

public route(stackstack)

}

public

class routenode

public routenodeparent

public

routenode(t value)

public routeroute

route

route = new route(stack);

return

route;}}

}

public

class 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是一種完備策略,即只要問題有解,它就一定可以找到解。並且,廣度優先搜尋找到的解,還一定是路徑最短的解。但是它盲目性較大,尤其是當目標節點距...