廣度優先遍歷(BFS)與深度優先遍歷(DFS)

一、廣度優先遍歷(圖的廣度優先遍歷類似於二叉樹的層序遍歷)

1、概念


(1)鄰接矩陣

  • 先從一個點出發,將其所有的鄰接點放到一個對列中
  • 當放完之後
  • 從隊頭的點開始,找是否有鄰接點,如果有的話,再從隊尾接上
  • 如果沒有就隊列頭部元素出隊,然後找新的對列元素時候有鄰接點,如果有的話,再從隊尾接上
  • 之後的過程一樣
  • 但按照這樣的方式找完之後,如果圖中還有沒有被訪問的點的話,就從未訪問的點開始進行同樣的過程

(2)鄰接表

在鄰接表中,如果已經給出了一個鄰接表,那麼在遍歷的時候,就有一定的順序,在鄰接表中,誰在前面,誰還沒有遍歷,則先遍歷誰,先將誰放到對列中。


2、框架

#include <bits/stdc++.h>

using namespace std;

const int maxn=100;
bool visit[maxn][maxn];//訪問標記//是否被訪問
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//方向向量
//如果向左運動的話,x+1,y+0,所以第一個代表向左運動
//如果向右運動的話,x-1,y+0,所以第二個代表向左運動
//如果向上運動的話,x+0,y+1,所以第三個代表向上運動
//如果向下運動的話,x+0,y-1,所以第四個代表向下運動

struct State//BFS對列中數據狀態
{
    int x,y;//座標位置
    int Strp_Counter;//搜索步數統計器
};
State a[maxn];

bool CheckState(State s)
{
    if(!visit[s.x][s.y]&&...)//滿足約束條件
        return 1;
    else
        return 0;
}

void bfs(State st)
{
    queue<State> q;//BFS對列
    State now,next;//定義兩個狀態,當前和下一個
    st.Strp_Counter=0;//計數器清0
    q.push(st);
    visit[st.x][st.y]=1;//訪問標記
    while(!q.empty())
    {
        now=q.front();
        if(now==G)//出現目標態,此時爲Step_Counter 的最小值,可以退出即可
        {
            ......//做相關處理
            return;
        }
        for(int i=0;i<4;i++)
        {
            next.x=now.x+dir[i][0]; // 按照規則生成下一個狀態
            next.y=now.y+dir[i][1];
            next.Strp_Counter=now.Strp_Counter+1;//計數器加1
            if(CheckState(next))
            {
                q.push(next);
                visit[next.x][next.y]=1;
            }
        }
        q.pop();//隊首元素出隊
    }
    return;
}


int main()
{
    ......
    return 0;
}

二、深度優先遍歷(圖的深度優先遍歷類似於二叉樹的先序遍歷)

 

1、概念


(1)鄰接矩陣

  • 訪問圖中的某一個頂點v
  • 從v的未被訪問的鄰接點出發到點v1,訪問v1的鄰接點,如果v1有未被訪問的鄰接點,那麼就繼續訪問這個未被訪問的鄰接點,否則回退到上一個點,一直回退到某一個含有未被訪問的鄰接的點爲止,然後繼續進行遍歷,如果按照這個方法遍歷完之後
  • 若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發,重新進行深度優先遍歷,直到圖中所有頂點均被訪問過爲止。
     

2、框架

#include <bits/stdc++.h>

using namespace std;

const int maxn=100;
bool visit[maxn][maxn];//訪問標記//是否被訪問
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//方向向量
//如果向左運動的話,x+1,y+0,所以第一個代表向左運動
//如果向右運動的話,x-1,y+0,所以第二個代表向左運動
//如果向上運動的話,x+0,y+1,所以第三個代表向上運動
//如果向下運動的話,x+0,y-1,所以第四個代表向下運動
int maps[maxn][maxn];//座標範圍



bool CheckEdge(int x,int y)//邊界和約束條件的判斷
{
    if(!visit[x][y]&&...)//約束條件
        return 1;
    else
        return 0;
}

void dfs(int x,int y)
{
    visit[x][y]=1;//標記該節點被訪問過
    if(maps[x][y]==G)// 出現目標態G
    {
        ......//做相應處理
        return;
    }
    for(int i=0;i<4;i++)
    {
        if(CheckEdge(x+dir[i][0],y+dir[i][1]))//按照規則生成下一個節點
        dfs(x+dir[i][0],y+dir[i][1]);
    }
    return;//沒有下層搜索節點,回溯
}


int main()
{
    ......
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章