圖-廣度優先搜索

簡介:

廣度優先搜索算法(又稱寬度優先搜索)是最簡便的圖的搜索算法之一,這一算法也是很多重要的圖的算法的原型。Dijkstra單源最短路徑算法和Prim最小生成樹算法都採用了和寬度優先搜索類似的思想。其別名又叫BFS,屬於一種盲目搜尋法,目的是系統地展開並檢查圖中的所有節點,以找尋結果。換句話說,它並不考慮結果的可能位置,徹底地搜索整張圖,直到找到結果爲止。

算法思想:

首先訪問起始頂點S,在一次訪問S所有尚未訪問到的鄰居;再按後者被訪問的先後次序,逐個訪問他們的鄰居…;直至搜索完所有能到達的頂點。類似樹結構中的層次遍歷。
在這裏插入圖片描述

算法步驟:
  1. 首先從起始頂點出發,訪問起始頂點
  2. 依次訪問起始頂點未曾訪問的鄰接頂點
  3. 分別從這些鄰接點出發依次訪問他們的鄰接點,並且保證先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點
  4. 重複3,直至無鄰接點可訪問爲止

根據上述特性,我們可以採用隊列暫存每個頂點。

  1. 起始頂點先入隊
  2. 彈出隊頭元素,查看其是否有未被訪問過的鄰接點,若有則入隊
  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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章