数据结构21————图的深度优先遍历(DFS)&广度优先遍历(BFS)
一. 目录
文章目录
二. 深度优先遍历(DFS)
1.DFS递归定义
假设给定图的所有状态都是未曾访问过.在G中任选一个点V作为初始点。则深度优先遍历的定义如下:
首先访问出发点V,并将其标记为已访问过。然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的处发点继续进行深度优先遍历,直至图中所有和源点v路径相通的顶点均被访问。若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。
图的深度优先遍历类似于图的前序遍历。采用搜索方法的特点是尽可能对纵深方向进行搜索。这种搜索方法被称为深度优先搜索(Depth-First Search)
2.遍历思路
- 访问顶点v;
- 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;
- 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。
3.伪代码
递归实现
(1)访问顶点v;visited[v]=1;//算法执行前visited[n]=0
(2)w=顶点v的第一个邻接点;
(3)while(w存在){
if(w未被访问)
从顶点w出发递归执行该算法;
w=顶点v的下一个邻接点;
}
非递归实现
(1) 栈S的初始化:visited[n=0]
(2) 访问顶点v;visited[v]=1;顶点v入栈s
(3) while(栈S非空){
x=栈S的顶元素(不出栈);
if(存在并找到未曾访问的x邻接点w){
访问w;visited[w]=1;
w入栈;
}else{
x出栈;
}
}
4.对邻接矩阵存储无向图的进行DFS
完整代码在下文链接中,下同
int visited[MAXVEX];
void DFS(AdjMatrix *G,int i){ //i为出发点
int j;
visited[i]=1;
printf("%c",G->Vex[i]);
for(j=0;j<G->vexnum ;j++){
if(G->acre[i][j]==1&&!visited[j]){
DFS(G,j);
}
}
}
void DFSTraveres(AdjMatrix *G){
int i;
for(i=0;i<G->vexnum;i++){
if(!visited[i]){ //对未访问的点,进行DFS,如果是联通图,只会执行一次
DFS(G,i);
}
}
}
5.对邻接表存储的无向图进行DFS
int visited[MAXVEX];
void DFS(AdjList *GL,int i){
ArcNode *p;
visited[i]=1;
printf("%c",GL->vertex[i].vexdata);
p=GL->vertex[i].head;
while(p){
if(!visited[p->adhVex]){
DFS(GL,p->adhVex);
}
p=p->next;
}
}
void DFSTraverse(AdjList *GL){
int i;
for(i=0;i<GL->vexnum;i++){
if(!visited[i]){
DFS(GL,i);
}
}
}
三. 广度优先遍历(BFS)
1.BFS的定义
图的广度优先遍历BFS算法是一个分层搜索的过程,和树的层序遍历算法类同,它也需要一个队列以保持遍历过的顶点顺序,以便按出队的顺序再去访问这些顶点的邻接顶点。
2.遍历思路
- 从图中某个顶点V0出发,并访问此顶点;
- 从V0出发,访问V0的各个未曾访问的邻接点W1,W2,…,Wk;然后,依次从W1,W2,…,Wk出发访问各自未被访问的邻接点;
- 重复步骤2,直到全部顶点都被访问为止。
3.伪代码
(1) 初始化对列Q;visited[n]=0
(2) 访问顶点v;visited[v]=1;顶点v入队列Q;
(3)while(队列Q非空){
v = 队列的队首元素出队;
w = 顶点v的第一个邻接点;
while(w存在){
如果w为访问,则访问顶点w;
visited[w]=1;
顶点w入队列Q;
w=顶点v的下一个邻接点.
}
}
4.对邻接矩阵存储无向图的进行BFS
int visited[MAXSIZE];
void BFSTraveres(AdjMatrix *G){
int i,j;
CSeQeue *Q;//队
Q=InitSeQueue();
for(i=0;i<G->vexnum;i++){
if(!visited[i]){ //对未访问的点,进行DFS,如果是联通图,只会执行一次
visited[i]=1;
printf("%c",G->Vex[i]);
InSeQueue(Q,i);//入队
while(!EmptySeQueue(Q)){ //如果当前队不为空
QutSeQueue(Q,&i);//出队
for(j=0;j<G->vexnum;j++){
if(G->acre[i][j]==1&&visited[j]==0){//如果邻接点存在并未访问过
visited[j]=1;
printf("%c",G->Vex[j]);
InSeQueue(Q,j);//入队
}
}
}
}
}
}
5.对邻接表存储的无向图进行BFS
int visited[MAXSIZE];
void BFSTraverse(AdjList *GL){
int i;
CSeQeue *Q;//队
Q=InitSeQueue();
ArcNode *p;
for(i=0;i<GL->vexnum;i++){
if(!visited[i]){
visited[i]=1;
printf("%c",GL->vertex[i].vexdata);
InitSeQueue(Q,i);//入队
while(!EmptySeQueue(Q)){
QutSeQueue(Q,&i);//出队
p=GL->vertex[i].head;
while(p){
if(!visited[p->adhVex]){//节点未被访问
visited[p->adhVex]=1;
printf("%c",GL->vertex[p->adhVex].vexdata);
InitSeQueue(Q,p->adhVex);//入队
}
p=p->next;
}
}
}
}
}
四. 源代码地址
五. 参考资料
《大话数据结构》
《数据结构与算法》
华山大师兄博客