簡介:
廣度優先搜索算法(又稱寬度優先搜索)是最簡便的圖的搜索算法之一,這一算法也是很多重要的圖的算法的原型。Dijkstra單源最短路徑算法和Prim最小生成樹算法都採用了和寬度優先搜索類似的思想。其別名又叫BFS,屬於一種盲目搜尋法,目的是系統地展開並檢查圖中的所有節點,以找尋結果。換句話說,它並不考慮結果的可能位置,徹底地搜索整張圖,直到找到結果爲止。
算法思想:
首先訪問起始頂點S,在一次訪問S所有尚未訪問到的鄰居;再按後者被訪問的先後次序,逐個訪問他們的鄰居…;直至搜索完所有能到達的頂點。類似樹結構中的層次遍歷。
算法步驟:
- 首先從起始頂點出發,訪問起始頂點
- 依次訪問起始頂點未曾訪問的鄰接頂點
- 分別從這些鄰接點出發依次訪問他們的鄰接點,並且保證先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點
- 重複3,直至無鄰接點可訪問爲止
根據上述特性,我們可以採用隊列暫存每個頂點。
- 起始頂點先入隊
- 彈出隊頭元素,查看其是否有未被訪問過的鄰接點,若有則入隊
- 重複上述過程,直至隊列爲空
爲了記錄定點是否被訪問過,我們可以使用一個標記數組,查看元素是否被訪問過。
代碼示例:
鄰接矩陣:
#include<iostream>
#include<queue>
using namespace std;
const int N = 100;
int graph[N][N];//鄰接矩陣存儲圖
bool visted[N];//標記數組
int seq[N];//記錄搜索順序
void init_graph(){//初始化鄰接矩陣
for(int i = 0; i < N; i++){//初始化鄰接矩陣
for(int j = 0; j < N; j++)
graph[i][j] = 0;
}
}
void bfs(int s, int n){
queue<int> q;
q.push(s);
visted[s] = true;
int count = 0;
while(q.size() > 0){
int t = q.front();
for(int i = 1; i <= n; i++){
if(graph[t][i] != 0){
if(!visted[i]){
visted[i] = true;
q.push(i);
}
}
}
seq[count++] = t;
q.pop();
}
}
int main(){
int n, m, s;
cin >> n >> m >> s;
init_graph();
for(int i = 0; i < m; i++){//輸入頂點與邊
int x, y;
cin >> x >> y;
graph[x][y] = 1;
}
bfs(s, n);
for(int i = 0; i < n; i++)
cout << seq[i] << " ";
return 0;
}
觀察上述代碼,不難發現,基本語句最壞情況下要執行n^ 2次,因此時間複雜度爲O(n^2)。
鄰接表:
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define MAX_SIZE 100
bool visted[MAX_SIZE];
typedef struct Enode{
int index;
Enode *next;
}*Edge;
struct Vnode{
int data;
Enode *next;
};
void init_v_node(Vnode *apex, int n){
for(int i = 0; i <= n; i++){
apex[i].data = 0;
apex[i].next = NULL;
}
}
void create_list(Vnode *apex, int m, int n){
for(int i = 0; i < m; i++){//更新圖的連通情況
int x, y;
cin >> x >> y;
apex[x].data = x;
Edge t = new Enode;
t->index = y;
t->next = apex[x].next;
apex[x].next = t;
}
}
void bfs(Vnode *apex, int s){
queue<int> q;
q.push(s);
visted[s] = true;
cout << s << " ";
while(q.size() > 0){
Edge p = apex[q.front()].next;
while(p != NULL){
if(!visted[p->index]){
cout << p->index << " ";
visted[p->index] = true;
q.push(p->index);
}
p = p->next;
}
q.pop();
}
}
int main(){
int n, m;
cin >> n >> m;
Vnode apex[n+1];//順序表存儲頂點
init_v_node(apex, n);
create_list(apex, m, n);
bfs(apex, 1);
return 0;
}