C语言数据结构---图的广度搜索

昨天学校连夜组织做核酸,西安的夜晚确实挺冷的,所以今天起的有点晚了,刚刚外面还在冒着雪花,

好了,闲话不多扯,开始介绍今天的主角—图的广度搜索遍历.

关于图的存储(邻接矩阵的方法)我在上一篇博文里面已经有介绍了.大家没有看的可以看看我的上一篇博文.

首先说一下他的原理吧:

基本思想:
从图的某个顶点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);
}

好了,今天这个任务完成了,感谢大家观看,
希望有不对的地方大家可以指出,一起进步.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值