广度优先搜索遍历,类似于层次遍历,从最初顶点开始,逐层对层内元素进行从左往右的遍历。
对于一个连通图,广度优先遍历过程如下:
(1)任取图中某个顶点,将其入队,并将该顶点标记为已访问;
(2)当队列不为空时循环操作:将队头顶点出队,依次检查出队顶点的从左往右的所有邻接点,访问没有被访问过的邻接点,并将其入队;
(3)当队列为空时跳出循环,遍历完成。
示例如下:
代码如下:(邻接表)
#include<stdio.h>
#define maxvertex 20
int que[maxvertex];
int front=0,rear=0;
typedef struct ArcNode{
int adjvex; //顶点对应的下标
struct ArcNode *nextarc;
}ArcNode;
typedef struct VerNode{
char data;
ArcNode *firstarc;
}adjList[maxvertex];
typedef struct{
adjList v;
int vertex; //顶点数
int arc; //边数
int visit[maxvertex]; //记录每个顶点是否被访问,0表示未被访问,1表示已被访问
}Graph;
void BFS(int x,Graph *G)
{ ArcNode *p;
int j;
printf("%c\n",G->v[x].data);
G->visit[x]=1; //标记该顶点为已访问
que[rear]=x; //将该顶点入队
rear=(rear+1)%maxvertex; //重置队列的队尾指针
while(front!=rear) //当队列不为空时进行循环
{
j=que[front]; //将队头元素出队
front=(front+1)%maxvertex; //重置队列的头指针
p=G->v[j].firstarc; //将x号顶点的邻接点赋给p
while(p)
{
if(G->visit[p->adjvex]==0)
{
printf("%c\n",G->v[p->adjvex].data);
G->visit[p->adjvex]=1; //将该顶点标记为已访问
que[rear]=p->adjvex; //将邻接点入队
rear=(rear+1)%maxvertex; //重置队列的尾指针
}
p=p->nextarc; //若有下一个邻接点,则将下一个邻接点地址赋给p,
//若没有,则p=NULL;
}
}
}
int main()
{
Graph G;
int v1,v2; //v1为边的开始顶点,v2为边的指向顶点
printf("请输入顶点数和边数:");
scanf("%d %d",&G.vertex,&G.arc);
getchar();
//初始化表头结点
for(int i=0;i<G.vertex;i++)
{
printf("请输入%d号顶点",i);
scanf("%c",&G.v[i].data);
getchar();
G.v[i].firstarc=NULL;
G.visit[i]=0;
}
//生成邻接表
for(int j=0;j<G.arc;j++)
{
printf("请输入边的序号(序号从0开始):");
scanf("%d %d",&v1,&v2);
ArcNode *p1,*q1;//生成边结点
p1=(ArcNode *)malloc(sizeof(ArcNode));
//q1=(ArcNode *)malloc(sizeof(ArcNode));
p1->adjvex=v2;
//p1->nextarc=G.v[v1].firstarc;
//G.v[v1].firstarc=p1;
p1->nextarc=NULL;
if(!G.v[v1].firstarc)
G.v[v1].firstarc=p1;
else
{
q1=G.v[v1].firstarc;
while(q1){
if(!q1->nextarc)
{
q1->nextarc=p1;
break;
}
q1=q1->nextarc;
}
}
ArcNode *p2,*q2;//生成边结点
p2=(ArcNode *)malloc(sizeof(ArcNode));
q2=(ArcNode *)malloc(sizeof(ArcNode));
p2->adjvex=v1;
p2->nextarc=NULL;
if(!G.v[v2].firstarc)
G.v[v2].firstarc=p2;
else
{
q2=G.v[v2].firstarc;
while(q2){
q2=q2->nextarc;
}
q2=p2;
}
}
int x;
printf("请输入开始顶点的编号:");
scanf("%d",&x);
BFS(x,&G);
}
运行结果如下:
代码如下:(邻接矩阵)
#include<stdio.h>
#define n 6 //顶点个数
struct element{
int visit[n] ;//记录是否被访问
char vex[n]; //顶点数组
int a[n][n];//边的邻接矩阵
int que[n];
};
void BFS(int v,struct element *G)
{
int front=0,rear=0;
G->que[rear]=v; //入队
rear=(rear+1)%n; //重置队尾指针
while(front!=rear)
{
int j;
j=G->que[front];//出队
front=(front+1)%n; //重置队头指针
if(G->visit[j]==0)
{
printf("%c\n",G->vex[j]); //打印第一个出队元素
G->visit[j]=1; //将出队顶点标志为已访问
}
for(int h=j+1;h<n;h++) //寻找出队顶点的邻接点
{
if(G->a[j][h]==1&&G->visit[h]==0) //两顶点间边存在,且另一顶点未被访问过
{
printf("%c\n",G->vex[h]);
G->que[rear]=h;
G->visit[h]=1;
rear=(rear+1)%n;
}
}
}
}
int main()
{
struct element G;
//初始化邻接矩阵
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(i==j)
G.a[i][j]=0;
else
G.a[i][j]=999; //设置999为无穷大
}
printf("请输入第%d号顶点:",i);
scanf("%c",&G.vex[i]); //输入顶点字母
getchar();
G.visit[i]=0;
}
//读入边
int edge,v1,v2;
printf("请输入边数:");
scanf("%d",&edge);
for(int k=0;k<edge;k++)
{
printf("请输入边(序号从0开始):");
scanf("%d %d",&v1,&v2);
G.a[v1][v2]=1;
G.a[v2][v1]=1;
}
int v;
printf("请输入开始的顶点编号:");
scanf("%d",&v);
BFS(v,&G);
}
运行结果: