廣度優先搜索(WFS Width-First Searching)
GitHub代碼: BFSShortestPath.java
總結
- WFS,數據結構採用 Queue
- enqueue 輸入init 節點
- dequeue 就是 出棧,並加入其 子節點
- DFS寬度優先,數據結構就是 Stack
- 遞歸自帶Stack效果,所以可遞歸
代碼
package _07._07;
import java.util.Vector;
import java.util.Stack;
import java.util.LinkedList;
import java.util.Queue;
public class ShortestPath {
private Graph G; // 圖的引用
private int s; // 起始點
private boolean[] visited; // 記錄dfs的過程中節點是否被訪問
private int[] from; // 記錄路徑, from[i]表示查找的路徑上i的上一個節點
private int[] ord; // 記錄每個節點到 s 的距離
// 構造函數, 尋路算法, 尋找圖graph從s點到其他點的路徑
public ShortestPath(Graph graph, int s){
// 算法初始化
G = graph;
assert s >= 0 && s < G.V();
visited = new boolean[G.V()];
from = new int[G.V()];
ord = new int[G.V()];
for( int i = 0 ; i < G.V() ; i ++ ){
visited[i] = false;
from[i] = -1;
ord[i] = -1;
}
this.s = s;
// 無向圖最短路徑算法, 從s開始廣度優先遍歷整張圖
Queue<Integer> q = new LinkedList<Integer>();
q.add(s);
visited[s] = true;
ord[s] = 0;
while( !q.isEmpty() ){
int v = q.remove();
for( int i : G.adj(v) )
if( !visited[i] ){
q.add(i);
visited[i] = true;
from[i] = v;
ord[i] = ord[v] + 1;
}
}
}
// 查詢從s點到w點是否有路徑
public boolean hasPath(int w){
assert w >= 0 && w < G.V();
return visited[w];
}
// 查詢從s點到w點的路徑, 存放在vec中
public Vector<Integer> path(int w){
assert hasPath(w) ;
Stack<Integer> s = new Stack<Integer>();
// 通過from數組逆向查找到從s到w的路徑, 存放到棧中
int p = w;
while( p != -1 ){
s.push(p);
p = from[p];
}
// 從棧中依次取出元素, 獲得順序的從s到w的路徑
Vector<Integer> res = new Vector<Integer>();
while( !s.empty() )
res.add( s.pop() );
return res;
}
// 打印出從s點到w點的路徑
public void showPath(int w){
assert hasPath(w) ;
Vector<Integer> vec = path(w);
for( int i = 0 ; i < vec.size() ; i ++ ){
System.out.print(vec.elementAt(i));
if( i == vec.size() - 1 )
System.out.println();
else
System.out.print(" -> ");
}
}
// 查看從s點到w點的最短路徑長度
// 若從s到w不可達,返回-1
public int length(int w){
assert w >= 0 && w < G.V();
return ord[w];
}
}
BFS 作用
- 是否存在A到B的路徑
- 從A開始 BFS 所有的節點
- 記錄節點是否被訪問的(visited 數組結構, boolean類型, i爲節點序號)
- 記錄當前節點 父節點(visited 數組結構, 序號類型, i爲節點序號)
- 從B節點,反向遍歷父節點,直至A節點(Stack結構)
- 打印Stack結構(路徑)
- 找出最短的路徑
- 設置visited array,只允許訪問一次
- 最早的一次訪問,一定是最短的路徑(當然,可能有多個最短,但只選擇了一個)
作用範圍
- 有向圖、二叉樹
- 無法作用於加權圖
- 加權圖(採用Dijkstra’s algorithm, 狄克斯特拉算法,之後更新)
時間複雜度
- O(節點數+邊數)= O(節點數) + O(邊數)
- O(邊數) 沿每條邊前行耗時
- O(節點數) 每個節點添加耗時
考題: 左側正三角形遍歷
- 輸入n,座標:爲n*n的矩形的 左下方三角形
- 每個座標上有數值
- 起始座標 0,0;只有一個item
- 下個座標,只允許當前座標的 down、right
- 終止條件,走到最後一行,即第n行
- 輸出 到達終止條件,路徑數值累加最大的,