圖的廣度優先遍歷演算法
阿新 • • 發佈:2019-01-08
前言
廣度優先遍歷演算法是圖的另一種基本遍歷演算法,其基本思想是盡最大程度輻射能夠覆蓋的節點,並對其進行訪問。以迷宮為例,深度優先搜尋更像是一個人在走迷宮,遇到沒有走過就標記,遇到走過就退一步重新走;而廣度優先搜尋則可以想象成一組人一起朝不同的方向走迷宮,當出現新的未走過的路的時候,可以理解成一個人有分身術,繼續從不同的方向走,,當相遇的時候則是合二為一(好吧,有點扯了)。
廣度優先遍歷演算法的遍歷過程
仍然以上一篇圖的深度優先遍歷演算法的例子進行說明,下面是廣度優先遍歷的具體過程:
- 從起點0開始遍歷
- 從其鄰接表得到所有的鄰接節點,把這三個節點都進行標記,表示已經訪問過了
- 從0的鄰接表的第一個頂點2開始尋找新的叉路
- 查詢頂點2的鄰接表,並將其所有的鄰接節點都標記為已訪問
- 繼續從頂點0的鄰接表的第二個節點,也就是頂點1,遍歷從頂點1開始
- 查詢頂點1的鄰接表的所有鄰接節點,也就是頂點0和頂點2,發現這兩個頂點都被訪問過了,頂點1返回
- 從頂點0的下一個鄰接節點,也就是頂點5,開始遍歷
- 查詢頂點5的鄰接節點,發現其鄰接節點3和0都被訪問過了,頂點5返回
- 繼續從2的下一個鄰接節點3開始遍歷
- 尋找頂點3的鄰接節點,發現都被訪問過了,頂點3返回
- 繼續尋找頂點2的下一個鄰接節點4,發現4的所有鄰接節點都被訪問過了,頂點4返回
- 頂點2的所有鄰接節點都放過了,頂點2返回,遍歷結束
廣度優先遍歷演算法的實現
與深度優先遍歷演算法相同,都需要一個標記陣列來記錄一個節點是否被訪問過,在深度優先遍歷演算法中,使用的是一個棧來實現的,但是廣度優先因為需要記錄與起點距離最短的節點,或者說能夠用盡可能少的邊連通的節點,距離短的優先遍歷,距離遠的後面再遍歷,更像是佇列。所以在廣度優先遍歷演算法中,需要使用佇列來實現這個過程。下面是具體的實現程式碼(已附詳細註釋):
package com.rhwayfun.algorithm.graph;
import java.util.LinkedList;
import java.util.Queue;
/**
* 廣度優先搜尋
* <p>Title:BreadFirstSearch</p>
* <p>Description:</p>
* @author rhwayfun
* @date Dec 23, 2015 4:43:41 PM
* @version 1.0
*/
public class BreadFirstSearch {
//建立一個標記陣列
private boolean[] marked;
//起點
private int s;
public BreadFirstSearch(MyGraph G, int s){
marked = new boolean[G.V()];
this.s = s;
//開始廣度優先搜尋
bfs(G,s);
}
private void bfs(MyGraph G, int s2) {
//建立一個佇列
Queue<Integer> queue = new LinkedList<Integer>();
//標記起點
marked[s] = true;
queue.add(s);
System.out.print(s + " ");
while(!queue.isEmpty()){
//從佇列中刪除下一個節點
int v = queue.poll();
//將該節點的所有鄰接節點加入佇列中
for(int w : G.adj(v)){
//如果沒有標記就標記
if(!marked[w]){
marked[w] = true;
System.out.print(w + " ");
queue.add(w);
}
}
}
}
}
執行該程式,發現廣度優先遍歷演算法對上圖的遍歷順序是0,2,1,5,3,4。