昨天学校连夜组织做核酸,西安的夜晚确实挺冷的,所以今天起的有点晚了,刚刚外面还在冒着雪花,
好了,闲话不多扯,开始介绍今天的主角—图的广度搜索遍历.
关于图的存储(邻接矩阵的方法)我在上一篇博文里面已经有介绍了.大家没有看的可以看看我的上一篇博文.
首先说一下他的原理吧:
基本思想:
从图的某个顶点V0出发,首先访问V0.
依次访问V0各个未被访问的邻接点.
分别从这些邻接点出发,依次访问他们的各个未被访问的邻接点.访问时应该保证:如果Vi和Vk为当前端结点,且Vi和Vk在之前未被访问,则Vi的所有未被访问的邻接点应在Vk所有未被访问的邻接点之前访问.重复
上述过程,直到所有端结点均没有未被访问过的邻接点为止.
注意:每个顶点设置一个标志用于检查是否访问过,
即设置数组visited[n],visited[i]=0 未访问
visited[i]=1 已访问
需要辅助队列Q,以便实现访问时应保证的一点.
1.访问出发点V0并置访问标志,然后将V0入队.
2.只要队不空,则重复下述处理.
a.队头结点V出队;
b.对V的所有邻接点W,如果W未被访问,则访问W并置访问标志,然后w入队.
我推荐大家看一下西安邮电大学的慕课,里面王春梅老师讲这个讲的很清楚.
那么了解了思路以后就直接上代码吧.
所以首先定义队列的结
typedef struct Squeue{
int data[MAXSIZE];//队列内元素的最大长度
int front;//队头
int rear;//队尾
}Squeue;
相较于深度遍历,广度遍历较难实现.我们需要借助队列实现.
//初始化队列
void InitQueue(Squeue *Q)
{
Q->front = Q->rear = 0;
}
//判断队列是否为空
int isQueueEmpty(Squeue *qu)
{
if(qu->front == qu->rear)
{
return 1;
}
else
{
return 0;
}
}
//元素入队操作
int EnQueue(Squeue *qu,int x)
{
if((qu->rear + 1) % MAXSIZE == qu->front)
{
return 0;
}
qu->rear = (qu->rear + 1) % MAXSIZE;
qu->data[qu->rear] = x;
return 1;
}
下面呢是完整代码:
#include<stdio.h>
#include<stdlib.h>
#define MAX 100 //定义最大数
#define INFINITY 0//定义无穷大
#define MAXSIZE 20 //定义队列元素的最大长度
typedef struct
{
char vexs[MAX];//存储顶点信息
int arc[MAX][MAX];//存储边信息
int numVertexes;//定义顶点数
int numEdges;//定义边数
int type; //定义图的类型
}MGraph;
typedef struct Squeue{
int data[MAX];//队列内元素的最大长度
int font;//队头指针
int rear;//队尾指针
}Squeue;
void InitQueue(Squeue * Q)//初始化队列
{
Q->font = Q->rear = 0;
}
int Empty(Squeue * Q)//判队空
{
if(Q->font == Q->rear)
{
return 1;
}
else
{
return 0;
}
}
int InQueue(Squeue * Q,int v)//入队函数
{
if((Q->rear+1)%MAXSIZE == Q->font )
{
return 0;
}
Q->rear = (Q->rear+1)%MAXSIZE;
Q->data[Q->rear] = v;//对元素入队
return 1;
}
int deleQueue( Squeue * Q,int *v)//出队函数
{
if(Q->font == Q->rear)//如果队空则无法出队
{
return 0;
}
Q->font = (Q->font+1)%MAXSIZE;
*v = Q->data[Q->font];
return 1;
}
void Create(MGraph * G)
{
int i,j,k,w;
printf("请输入图的顶点数和边数");
scanf("%d %d",&(G->numVertexes),&(G->numEdges));
fflush(stdin);
for(i=0;i<G->numVertexes;++i)
{
printf("请输入No.%d个顶点: ",i+1);
scanf("%c",&G->vexs[i]);
getchar();
}
for(i=0;i<G->numVertexes;++i)
{
for(j=0;j<G->numVertexes;++j)
{
G->arc[i][j]=INFINITY;
}
}
for(k=0;k<G->numEdges;++k)
{
printf("输入边(Vi,Vj)的上下标i,j和权w(空格隔开):");
scanf("%d %d %d",&i,&j,&w);
G->arc[i][j]=w;
// if(G->type==0)
// {
// G->arc[j][i]=G->arc[i][j];
// }
}
}
void BFS(MGraph * G)
{
int i,f,r;
int w,v;
int visited[G->numVertexes];
Squeue Q;
InitQueue(&Q);//初始化队列
for(i=0;i<G->numVertexes;++i)
{
visited[i]=0;//初始化标记数列
}
for(v=0;v<G->numVertexes;++v)
{
if(!visited[v])
{
visited[v]=1;//已经访问,则标记为1
printf("%c->",G->vexs[v]);
InQueue( &Q, v);
while(!Empty(&Q))
{
int u;
deleQueue( &Q, &u);
for(i=0;i<G->numVertexes;++i)
{
if(G->arc[u][i]&&visited[i]==0)
{
visited[i]=1;
printf("%c->",G->vexs[i]);
InQueue(&Q,G->vexs[i]);
}
}
}
}
}
}
void Output(MGraph * G)
{
int i,j,count=0;
for(i=0;i<G->numVertexes;++i)
{
printf("\t%c",G->vexs[i]);
}
printf("\n");
for(i=0;i<G->numVertexes;++i)
{
printf("%4c",G->vexs[i]);
for(j=0;j<G->numVertexes;++j)
{
printf("\t%d",G->arc[i][j]);
count++;
if(count%G->numVertexes==0)
{
printf("\n");
}
}
}
}
int main()
{
MGraph G;
Create(&G);
BFS(&G);
printf("\n输入的邻接矩阵如下:\n");
Output( &G);
}
好了,今天这个任务完成了,感谢大家观看,
希望有不对的地方大家可以指出,一起进步.