廣度優先搜尋與深度優先遍歷
阿新 • • 發佈:2019-01-03
廣度優先搜尋
有一個有向圖如圖a:
圖a
廣度優先搜尋的策略是:
假設我們以頂點0為原點進行搜尋,首先確定鄰接0的頂點集合S0 = {1,2},然後確定頂點1的集合S1 = {3},頂點2沒有鄰接點,所以集合為空。然後確定3的鄰接點集合S3,因為2已經被遍歷過,所以不考慮,所以由頂點3知道的鄰接點集合S3 = {4},然後再確定頂點4的鄰接點集合,頂點4沒有更多的鄰接點了,此時也沒有還未遍歷的鄰接點集合,搜尋終止。
遍歷的路徑可以參考如下圖紅色標記的路徑:
程式碼的實現思路:
BFS()
{
輸入起始點; 初始化所有頂點標記; 初始化一個佇列queue並將起始點放入佇列;while(queue不為空) {
從佇列中刪除一個頂點s並標記為已遍歷; //表示遍歷了s 將s鄰接的所有還沒遍歷的點加入佇列; }
}
深度優先遍歷
繼續以圖a為例
圖a
深度優先遍歷的策略是:
從一個頂點v出發,首先將v標記為已遍歷的頂點,然後選擇一個鄰接於v的尚未遍歷的頂點u,如果u不存在,本次搜素終止。如果u存在,那麼從u又開始一次DFS。如此迴圈直到不存在這樣的頂點。比如從圖中頂點0開始,將0標記為已遍歷,然後選擇未被遍歷的鄰接0的頂點1,標記頂點1,然後選擇3並標記,然後選擇3鄰接的2,2標記後沒有與它鄰接的未標記的點,所以返回3選擇另一個鄰接3並且未被標記的頂點4,頂點4沒有更多的符合條件的點,因此搜尋終止,返回到3,3沒有更多的點,搜尋終止返回到1,最後返回到0,搜尋終止。
遍歷的路徑可以參考如下圖紅色標記的路徑:
程式碼的實現思路:
DFS(頂點v) { 標記v為已遍歷; for(對於每一個鄰接v切未標記遍歷的店u) DFS(u); }
一個簡單的應用
實現的程式碼如下(C#):
public class Solution { public void dfs(int [,]M,int []visit,int i) { for(int j = 0;j < M.GetLength(0);j++) { if(M[i,j] == 1 && visit[j] == 0) { visit[j]= 1; dfs(M,visit,j); } } } public void bfs(int [,]M,int []visit,int i) { Queue<int> q = new Queue<int>(); q.Enqueue(i); while(q.Count > 0) { int temp = q.Dequeue(); for(int j = 0;j < M.GetLength(0);j++) { if(M[temp,j] == 1 && visit[j] == 0) { visit[j] = 1; q.Enqueue(j); } } } } public int FindCircleNum(int[,] M) { int N = M.GetLength(0); int circle = 0; //朋友圈數 int[] visit = new int[N]; for(int i = 0;i < N;i++) { if(visit[i] == 0) //還沒被訪問過 { //dfs(M,visit,i); //使用dfs搜尋並標記與其相關的學生 bfs(M,visit,i); //使用bfs搜尋並標記與其相關的學生 circle++; } } return circle; } }