广度优先遍历(BFS)
树的遍历:不存在“回路”,搜索相邻的结点时,不可能搜到已经访问过的结点
图的遍历:搜索相邻的顶点时,有可能搜到已经访问过的顶点
要点:
- 找到与一个顶点相邻的所有顶点
- 标记哪些顶点被访问过
- 需要一个辅助队列
- FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号,若x没有邻接点或图中不存在x,则返回-1
- NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
bool visited[MAX_VERTEX_NUM]; //访问标记数组
bool visited[MAX_VERTEX_NUM]; //访问标记数组
//广度优先遍历
void BFS(Grapg G,int v){ //从顶点v出发,广度优先遍历图G
visit(v); //访问初始顶点v
visited[v]=TRUE; //对v做已访问标记
Enqueue(Q,v); //顶点v入队列Q
while(!isEmpty(Q)){
DeQueue(Q,v); //顶点v出队列
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
//检测v所有邻接点
if(!visited[w]){ //w为v的尚未访问的邻接顶点
visit(w); //访问顶点w
visited[w]=TRUE; //对w做已访问标记
EnQueue(Q,w); //顶点w入队列
}//if
}//while
}
同一个图的邻接矩阵表示方式唯一,因此广度优先遍历序列唯一
同一个图邻接表表示方式不唯一,因此广度优先遍历序列不唯一
BFS算法(Final版)
bool visited[MAX_VERTEX_NUM]; //访问标记数组
void BFSTraverse(Graph G){ //对图G进行广度优先遍历
for(i=0;i<G.vexnum;++i)
visited[i]=FALSE; //访问标记数组初始化
InitQueue(Q); //初始化辅助队列Q
for(i=0;i<G.vexnum;++i) //从0号顶点开始遍历
if(!visited[i]) //对每个连通分量调用一次BFS
BFS(G,i); //vi未访问过,从vi开始BFS
}
//广度优先遍历
void BFS(Grapg G,int v){ //从顶点v出发,广度优先遍历图G
visit(v); //访问初始顶点v
visited[v]=TRUE; //对v做已访问标记
Enqueue(Q,v); //顶点v入队列Q
while(!isEmpty(Q)){
DeQueue(Q,v); //顶点v出队列
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighbor(G,v,w))
//检测v所有邻接点
if(!visited[w]){ //w为v的尚未访问的邻接顶点
visit(w); //访问顶点w
visited[w]=TRUE; //对w做已访问标记
EnQueue(Q,w); //顶点w入队列
}//if
}//while
}
用于解决非连通图
对于无向图,调用BFS函数的次数=连通分量数
广度优先生成树
广度优先生成树由广度优先遍历过程确定。由于邻接表的表示方式不唯一,因此基于邻接表的广度优先生成树也不唯一
广度优先生成森林
深度优先遍历(DFS)
bool visited[MAX_VERTEX_NUM];
void DFS(Graph G,int v){ //从顶点v出发,深度优先遍历图G
visit(v); //访问顶点v
visited[v]=TRUE; //设已访问标记
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighor(G,v,w))
if(!visited[w]){ //w为u的尚未访问的邻接顶点
DFS(G,w);
}//if
}
DFS算法(Final版)
bool visited[MAX_VERTEX_NUM] //访问标记数组
void DFSTraverse(Graph G){ //对图G进行深度优先遍历
for(v=0;v<G.vexnum;++v)
visited[v]=FALSE; //初始化已访问标记数据
for(v=0;v<G.vexnum;++v) //本代码中是从v=0开始遍历
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v){ //从顶点v出发,深度优先遍历图G
visit(v); //访问顶点v
visited[v]=TRUE; //设已访问标记
for(w=FirstNeighbor(G,v);w>=0;w=NextNeighor(G,v,w))
if(!visited[w]){ //w为u的尚未访问的邻接顶点
DFS(G,w);
}//if
}
解决非连通图
同一个图的邻接矩阵表示方式唯一,因此深度优先遍历序列唯一
同一个图邻接表表示方式不唯一,因此深度优先遍历序列不唯一
图的遍历与图的连通性
对无向图进行BFS/DFS遍历
调用BFS/DFS函数的次数=连通分量数
对于连通图,只需调用1次BFS/DFS
对有向图进行BFS/DFS遍历
调用BFS/DFS函数的次数要具体问题具体分析
若起始顶点到其他各顶点都有路径,则只需调用1次
BFS/DFS函数
对于强连通图,从任一结点出发都只需调用1次BFS/DFS