一、廣度優先遍歷(圖的廣度優先遍歷類似於二叉樹的層序遍歷)
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;
}