图的遍历:从图中某个顶点出发,不重复的访遍图中所有顶点。
一、DFS深度优先遍历(一个支路一个支路的)
基本思想:
从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到。——访问标记,访问与它相连且未被访问的点,如果周围的点都被访问过了,那就后退一步。
//一个图的深搜
void dfs(int x)
{
visited[x]=true;//标记x被访问
for(int i=0;i<g[x].size();i++)//g[x].size()表示与x相连的点的个数
if(!visited[i])
dfs(i);
//遍历x的相邻结点,若没被访问则从这个结点开始深搜遍历
}
//多个图深搜遍历
const int MAXN=1000+10;
vector<int> g[MAXN];
bool visited[MAXN];
int main()
{
for(int i=1;i<=MAXN;i++)
g[i].clear();
memset(visited,0,sizeof(visited));
//初始化清空g和visited数组
for(int i=1;i<=MAXN;i++)
if(!visited[i])
dfs(i);
} //只执行了每个图的顶点的dfs,其他的因为visited都是1,所以不管它==
二、BFS广度优先搜索(一层一层的)
基本思想:
从某个顶点V0出发,并在访问此顶点之后依次访问V0的所有未被访问过的邻接点,之后按这些顶点被访问的先后次序依次访问它们的邻接点,直至图中所有和V0有路径相通的顶点都被访问到。
//第一层进去了,出来后,第二层再进去,队头元素踢出去后,相连的未被访问的进来
const int MAXN=1000+5;
queue<int> q;
bool visited[MAXN];
初始化清空:
while(!q.empty())
q.pop();
memset(visited,0,sizeof(visited));
void bfs()
{
visited[1]=1;//初始结点1进入队列
q.push(1);
while(!q.empty())//队列为空时结束遍历
{
int t=q.front();
q.pop();
//寻找队头元素的相邻结点并弹出对头元素
for(int i=0;i<g[t].size();i++)
if(!visited[i])
{
q.push(i);
visited[i]=1;
//访问相邻结点并使之入队
}
}
}
三、tips
1.用DFS求连接块,通过递归实现;用BFS求最短路,通过队列实现。
2.很多复杂的迷宫问题都可以转化为最短路问题,然后用BFS求解。
(1)在套用BFS框架之前,要先搞清楚图中的“结点”包括哪些内容。
(2)用BFS求出最短路后,可以用递归打印最短路的具体路径。
(3)如果最短路非常长,递归可能会引起栈溢出,此时可以改用循环,用vector保存路径。