图的广度搜索,明确是无向图,根据提示示例,分析下列代码:
1.首先给出程序示例输入输出:
2.然后贡献详细代码
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
int visited[MAX]={0};//定义一个访问标志数组
typedef struct //定义一个结构体代表顺序队列
{
int front;
int rear;
int data[MAX];
}Queue;
typedef struct //定义一个结构体代表图的邻接矩阵
{
int vexs[MAX];
int arcs[MAX][MAX];
int vexnum,arcnum;
}Graph;
void InitQueue(Queue *q);//队列的初始化
int EmptyQueue(Queue *q);//判断队列非空
int DeQueue(Queue *q);//出队
void EnQueue(Queue *q,int data);//入队
void CreateUDN(Graph &G);//创建图的邻接矩阵
int LocateVex(Graph G,int v);//确定顶点数组的下标
void BFS(Graph G,int v);//图的广度搜索
int FirstAdjVex(Graph G,int v);//选定点的第一个临接点
int NextAdjVex(Graph G,int v,int w);//相对于第一个选定点的下一个临接点,w大于等于0代表存在临接点
main()
{
Graph G;//创建图G
CreateUDN(G);// 对图G进行初始化,以此确定图G的结构
int i;
scanf("%d",&i);//输入从哪一个点进行图的广度搜索
BFS(G,i);//对图G进行广度搜索
}
void InitQueue(Queue *q)
{
q->front=q->rear=0; //初始化队列,置空
}
int EmptyQueue(Queue *q)
{
if(q->rear==q->front) //若队列头位置等于队列尾位置,代表队列为空
return 1;
else
return 0;
}
void EnQueue(Queue *q,int data)
{
if((q->rear+1)%MAX==q->front)//若环形队列队满,退出
exit(0);
q->data[q->rear]=data;//元素入队
q->rear=(q->rear+1)%MAX;//队头向前移位(这里是环形队列的创建,不多解释)
}
int DeQueue(Queue *q)
{
int data;
if(q->front==q->rear) //若队列为空,无法出队
return 0;
data=q->data[q->front]; //队列不为空,出对尾元素,即先出先进来的元素
q->front=(q->front+1)%MAX; //环形队列 对尾向前移位
return data;
}
void CreateUDN(Graph &G)
{
scanf("%d%d",&G.vexnum,&G.arcnum); //输入图的节点数和边数
int i,j,k;
for(i=0;i<G.vexnum;i++){ //输入所有节点值
scanf("%d",&G.vexs[i]);
}
for(i=0;i<G.vexnum;i++) //为图创建邻接矩阵
{
for(j=0;j<G.vexnum;j++)
{
G.arcs[i][j]=0; //初始化邻接矩阵为0
}
}
for(k=0;k<G.arcnum;k++)
{
int v1,v2,w;
scanf("%d%d%d",&v1,&v2,&w); //输入边的起始点和终点,并赋权值
i=LocateVex(G,v1); //确定起始点在邻接矩阵中的下标表示
j=LocateVex(G,v2); //确定终点在邻接矩阵中的下标表示
G.arcs[i][j]=w;
G.arcs[j][i]=G.arcs[i][j]; //无向图对称
}
}
int LocateVex(Graph G,int v) //确定某点在邻接矩阵中下标的具体方法
{
int i=0;
while ((v!=G.vexs[i])&&(i<G.vexnum))
i++;
return i;
}
void BFS(Graph G,int v)
{
printf("%d",v); //首先输出起始遍历的点
visited[v]=1; //对起始点进行标记,表示已经访问过v点,以后不用再次访问
int w;
int u;
Queue Q; //创建队列Q,用来对已访问点做标记
InitQueue(&Q); //初始化队列
EnQueue(&Q,v); //元素v入队
while(!EmptyQueue(&Q)) //队列不为空,执行while循环
{
u=DeQueue(&Q); //元素出队
for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))//依次检查u的所有临接点(按程序往下看,可以读懂,不多解释)
{
if(!visited[w]) //若没有访问过此点,即此点数组值为0,进行打印输出
{
printf("%d",w); //打印第一次访问的点
visited[w]=1; //对访问的这个点做标记,对数组值赋一,表示已经遍历此点
EnQueue(&Q,w); //将访问的此点入队 ,进入下次循环,找此点另外没有访问过的临接点
}
}
}
}
int FirstAdjVex(Graph G,int v) //自己按示例数据分析此方法,不多解释
{
int i=0;
while((i<G.vexnum)&&(G.arcs[v][i]==0))
i++;
if (i==G.vexnum)
return -1;
else
return i;
}
int NextAdjVex(Graph G,int v,int w)
{
int i=0;
for(i=w+1;(i<G.vexnum)&&((G.arcs[v][i]==0));i++) //这里循环找临接点,循环内部不需要执行任何代码,和上边找第一个点中的while类似
{}
if (i==G.vexnum)
return -1;
else
return i;
}