Transcript 縱向優先搜尋
8.2 縱向優先搜尋(depth first search)
問題:對於一個圖 G = (V, E) ,任給兩個頂點 i , j,試找
一條連接頂點 i 與頂點 j 的路徑。
我們可以利用縱向優先的方式來尋找這種路徑,縱向優先
的基本精神是:
如果前面有路可以走,就繼續往前搜尋,直到無路可走,
如果無路可走,就折返原路,一直找到有新的路可以走,
再依相同的方式進行,直到找到目的地,不然,找遍所有
路徑也找不到目的地。
例:一個簡單圖如下所示。
v0
v2
v1
v3
v5
v4
v6
v7
v8
試找一條連接頂點 3 與頂點 7 的路徑。
依該圖的 adjacency matrix 或 adjacency list 由 v3 走向 v0,再
走向v1及v6。此時無路可走,就往回走。以圖表示如下:
v0
走的方向以箭頭表
示,走訪過的頂點
以白色顯示。
v2
v1
v3
v5
v4
v6
v7
v8
走到 v6 時,確定無路可走,就
往回走。將 v6 改成藍色,再折
回v1, v1 也無路可走,再折回
v0,發現有新路 v2 可走。
v0
v2
v1
v3
v5
v4
v6
v7
v8
v0
由 v2 走向 v4,再走向 v5。此時
又發現無路可走,就往回走。
v2
v1
v3
v5
v4
v6
v7
v8
走到 v5 時,確定無路可走,就
往回走。折回 v4,發現有新路
v7 可走。v7 是目的地,整個路
徑由粗黑色箭頭連接而成。
v0
v2
v1
v3
v4
v6
v7
< v3,v0,v2, v4,v7>
v5
v8
以程式來處理路徑搜尋的問題,我們需要:
一個 adjacency matrix or adjacency list。
一個堆疊 s,將走訪的頂點 push 到堆疊,將無路可走的頂
點 pop 出堆疊,最後搜尋的路徑就是存在堆疊的資料。
一個陣列 visit 記錄頂點尚未走訪、走訪過與無路可走的資
料,分別以 0,1,2 表示。
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
0
1
1
1
0
0
1
0
0
1
1
1
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
1
1
1
0
0
0
0
1
0
1
0
1
1
0
0
1
1
0
1
0
1
1
0
1
0
1
0
0
0
0
1
0
1
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
1
0
0
0
0
adjacency matrix M
0
1
2
3
4
5
6
7
8
visit 0
0
0
0
0
0
0
0
0
stack s
例:由下列簡單圖找一條連接頂點 3 與頂點 7 的路徑。
v0
v2
先將頂點 3 push 到堆疊 s,同時
註明頂點 3 是已經走訪的頂點,
即 visit[3] =1。
v1
v3
v5
v4
v6
0
1
2
3
4
5
6
7
8
visit 0
0
0
1
0
0
0
0
0
v7
v8
3
stack s
由堆疊最上的頂點 3 來查 adjacency matrix M 頂點 3 那一列,
可以找到頂點 0, 2, 4, 6, 7與頂點 3 相鄰。 由縱向優先,頂點 0
的 visit[0] = 0 知道頂點 0 尚未走訪,因此,將頂點 0 push 到
堆疊上,visit[0] 改成 1。
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
0
1
1
1
0
0
1
0
0
1
1
0
0
0
0
0
1
0
0
0
0
1
1
1
0
0
0
0
1
0
1
0
1
1
0
0
1
1
0
1
0
1
1
0
1
0
1
0
0
0
0
1
0
1
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
1
0
0
0
0
1
0
0
1
0
0
0
1
2
3
4
5
6
7
8
visit 1
0
0
1
0
0
0
0
0
0
3
stack s
由堆疊最上的頂點 0 來查 adjacency matrix M 第 0 列,由縱向
優先可以找到頂點 1 與頂點 0 相鄰,且 visit[1] = 0 知道頂點 1
尚未走訪,因此,將頂點 1 push 到堆疊上,visit[1] 改成 1。
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
0
1
1
1
0
0
1
0
0
1
1
1
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
1
1
1
0
0
0
0
1
0
1
0
1
1
0
0
1
1
0
1
0
1
1
0
1
0
1
0
0
0
0
1
0
1
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
1
0
0
0
0
0
1
2
3
4
5
6
7
8
visit 1
10
0
1
0
0
0
0
0
1
0
3
stack s
由堆疊最上的頂點 1 找到頂點 0 與頂點 1 相鄰,但 visit[0] = 1
知道頂點 1 已走訪過,因此跳過頂點 0。
繼續往前找,找到頂點 6 與頂點 0 相鄰,且 visit[6] = 0 知道頂
點 6 尚未走訪,將頂點 6 push 到堆疊上,visit[6] 改成 1。
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
0
1
1
1
0
0
1
0
0
1
1
1
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
1
1
1
0
0
0
0
1
0
1
0
1
1
0
0
1
1
0
1
0
1
1
0
1
0
1
0
0
0
0
1
0
0
1
1
0
0
0
0
0
0
0
1
0
0
0
0
0
1
0
0
0
0
0
0
1
2
3
4
5
6
7
8
visit 1
1
0
1
0
0
10
0
0
6
1
0
3
stack s
由堆疊最上的頂點 6 找到頂點 0,1,3 與頂點 6 相鄰,但
visit[0] = visit[1] = visit[3] = 1 知道頂點 0,1,3 皆已走訪過,
因此無路可走。
將頂點 6 從堆疊 pop 出去,並將 visit[6] 改成 2。
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
0
1
1
1
0
0
1
0
0
1
1
1
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
1
1
1
0
0
0
0
1
0
1
0
1
1
0
0
1
1
0
1
0
1
1
0
1
0
1
0
0
0
0
1
0
0
1
1
0
0
0
0
0
0
0
1
0
0
0
0
0
1
0
0
0
0
0
0
1
2
3
4
5
6
7
8
visit 1
1
0
1
0
0
21
0
0
6
1
0
3
stack s
再由堆疊最上的頂點 1 找不到路,將頂點 1 pop 出堆疊,由頂
點 0 繼續往前找,找到頂點 2,由頂點 2找到頂點 4,由頂點 4
找到頂點 5 ,由頂點 5 折回頂點 4 ,由頂點 4 找到頂點 7。此
時的陣列 visit 與 stack s 的內容如下:
v0
v2
v1
v5
v3
v4
v6
v7
v8
0
1
2
3
4
5
6
7
8
visit 1
2
1
1
1
2
2
1
0
7
4
2
0
3
stack s
以縱向優先的方式,來處理路徑搜尋問題的程式如下:
scanf(“%d %d”, &i, &j);
foundDestination = FALSE; push(i); visit[i]=1;
while(!foundDestination ){
if(isStackEmpty()) break;
current = topOfStack( );// not pop()
findPath = FALSE;
for(k=0; k<n; k++){
if(M[i][k]==1 && visit[k]==0){
findPath = TRUE;
push(k); visit[k]=1;
if(k==j){foundDestination = TRUE;
break;}}// if case
}//for loop
if(!findPath)pop();//retreat one step
}
// The path now is left in the stack