一、广度优先遍历(图的广度优先遍历类似于二叉树的层序遍历)
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;
}