图的广度优先遍历BFS(邻接矩阵实现)c语言

 

广度优先遍历也叫广度优先搜索(Breadth First Search)。

它的遍历规则:

  1. 先访问完当前顶点的所有邻接点。
  2. 先访问的顶点的邻接点先于后访问顶点的邻接点被访问。

 

算法思想

 

使用队列的数据结构(FIFO (First In First Out)),将一个顶点加入队列,然后在队列中删除顶点,并且将该顶点相连的所有顶点依次加入队列中,再循环处理这些顶点,直至所有顶点均被访问。(类似树的层序遍历)

算法所需:

对队列的基本操作熟悉

 

代码实现如下:

#include<stdio.h>
#include<stdlib.h>

#define MAX 10
#define INFINITY 65535
#define TRUE 1
#define FALSE 0

typedef char VertexType;
typedef int EdgeType;

typedef int Boole;  //布尔类型 存储TRUE FALSE
Boole visited[MAX];    //访问标志数组 

typedef int QElemType;    //链队列的数据类型 
typedef int Status; 


/*邻接矩阵结构*/ 
typedef struct
{
	VertexType vexs[MAX];   //顶点表 
	EdgeType arc[MAX][MAX];   //邻接矩阵 可看作边表   
	int numVertexes,numEdges;   //顶点数和边数 
}MGraph;

/*队列结构*/
typedef struct QNode
{
	QElemType data;
	struct QNode *next;
}QNode,*QueuePtr;

typedef struct
{
	QueuePtr front,rear;  //队头队尾指针 
}LinkQueue;
 

//构造邻接矩阵
void create(MGraph *G)
{
	int i,j,k,w;
	printf("请输入顶点数和边数:\n");
	scanf("%d%d",&G->numVertexes,&G->numEdges);
	fflush(stdin);
	for(i=0;i<G->numVertexes;i++)     //建立顶点表
	{ 
		printf("\n第%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;
		G->arc[j][i]=G->arc[i][j];
	}			 
} 

  //输出邻接矩阵 
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");	
		} 
    }	 
 } 
 

//创建空队列
Status InitQueue(LinkQueue &Q)
{
	Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
	if(!Q.front)
		exit(0);
	Q.front->next=NULL;
	return 1;	
} 

//入队列
//将s作为新元素加入队尾 
Status EnQueue(LinkQueue &Q,int i)
{
	QueuePtr s;
	s=(QueuePtr)malloc(sizeof(QNode));
	if(!s)
		exit(0);
	s->data=i;
	s->next=NULL;
	Q.rear->next=s;
	Q.rear=s;
	return 1;	
}

//检验是否为空
Status QueueEmpty(LinkQueue Q)
{
	if(Q.front->next==NULL)
		return 0;
	else
		return 1;	
 } 

//出队列
Status DeQueue(LinkQueue *Q,int *i)
{
	QueuePtr p;
	if(Q->front==Q->rear)
		return 0;
	p=Q->front->next;     //该写法值得商榷
						//相当于p储存第一个结点
	*i=p->data;
	Q->front->next=p->next;
	
	if(p==Q->rear)   //若队头是队尾	,删除后将rear指向头结点		
		Q->rear==Q->front;
	free(p);
	return 1;			
 } 



/*广度遍历*/ 
void BFSTraverse(MGraph G)
{

	int i,j;
	LinkQueue Q;
	for(i=0;i<G.numVertexes;i++)
		visited[i]=FALSE;
	InitQueue(Q);          //&的用法??     初始化队列    
	for(i=0;i<G.numVertexes;i++)
	{
		if(!visited[i])    //未访问过 该顶点 
		{
			visited[i]=TRUE;
			printf("%c->",G.vexs[i]);
			EnQueue(Q,i);      //将其入队列 
			while(!QueueEmpty(Q))
			{
				DeQueue(&Q,&i);    //将队中元素出队列,赋值给i 
				for(j=0;j<G.numVertexes;j++)
				{
					if(G.arc[i][j]==1&&!visited[j])      //其他顶点与该顶点存在边   且未访问过 
					{
						visited[j]=TRUE;
						printf("%c",G.vexs[j]);
						EnQueue(Q,j);                 //入队列 
					}
					
				} 
			} 
		}
	}
} 


int main()
{
	MGraph G;
	create(&G);
	printf("邻接矩阵数据如下:\n");
	Output(&G);
	printf("\n");
	BFSTraverse(G); 
	printf("\n图遍历完毕");
	return 0;	 
	
} 


 

 

 

 

 

 

  • 24
    点赞
  • 144
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
邻接矩阵实现的深度优先遍历和广度优先遍历: 深度优先遍历: 1. 定义一个栈,将起始节点入栈。 2. 当栈不为空时,取出栈顶节点,访问该节点,并将其未被访问的邻居节点入栈。 3. 标记已访问的节点。 4. 重复步骤2和3,直到栈为空。 邻接矩阵实现深度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 #define INFINITY 65535 //表示无穷大 typedef struct { int vexs[MAX_VERTEX_NUM]; //顶点表 int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵 int vexnum, arcnum; //的当前顶点数和弧数 } MGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void DFS(MGraph G, int v) { visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vexs[v]); //访问节点v for (int i = ; i < G.vexnum; i++) { if (G.arcs[v][i] != INFINITY && !visited[i]) { //如果节点i是节点v的邻居且未被访问 DFS(G, i); //递归访问节点i } } } void DFSTraverse(MGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 DFS(G, i); //从节点i开始深度优先遍历 } } } ``` 广度优先遍历: 1. 定义一个队列,将起始节点入队。 2. 当队列不为空时,取出队首节点,访问该节点,并将其未被访问的邻居节点入队。 3. 标记已访问的节点。 4. 重复步骤2和3,直到队列为空。 邻接矩阵实现广度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 #define INFINITY 65535 //表示无穷大 typedef struct { int vexs[MAX_VERTEX_NUM]; //顶点表 int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵 int vexnum, arcnum; //的当前顶点数和弧数 } MGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void BFS(MGraph G, int v) { int queue[MAX_VERTEX_NUM]; //定义队列 int front = , rear = ; //队首和队尾指针 visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vexs[v]); //访问节点v queue[rear++] = v; //将节点v入队 while (front != rear) { //队列不为空时 int w = queue[front++]; //取出队首节点w for (int i = ; i < G.vexnum; i++) { if (G.arcs[w][i] != INFINITY && !visited[i]) { //如果节点i是节点w的邻居且未被访问 visited[i] = 1; //标记节点i已被访问 printf("%d ", G.vexs[i]); //访问节点i queue[rear++] = i; //将节点i入队 } } } } void BFSTraverse(MGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 BFS(G, i); //从节点i开始广度优先遍历 } } } ``` 邻接表实现的深度优先遍历和广度优先遍历: 深度优先遍历: 1. 定义一个栈,将起始节点入栈。 2. 当栈不为空时,取出栈顶节点,访问该节点,并将其未被访问的邻居节点入栈。 3. 标记已访问的节点。 4. 重复步骤2和3,直到栈为空。 邻接表实现深度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 typedef struct ArcNode { //边表节点 int adjvex; //邻接点在顶点表中的位置 struct ArcNode *nextarc; //指向下一个边表节点 } ArcNode; typedef struct VNode { //顶点表节点 int data; //顶点数据 ArcNode *firstarc; //指向第一个边表节点 } VNode, AdjList[MAX_VERTEX_NUM]; typedef struct { AdjList vertices; //邻接表 int vexnum, arcnum; //的当前顶点数和弧数 } ALGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void DFS(ALGraph G, int v) { visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vertices[v].data); //访问节点v ArcNode *p = G.vertices[v].firstarc; while (p) { if (!visited[p->adjvex]) { //如果节点p->adjvex未被访问 DFS(G, p->adjvex); //递归访问节点p->adjvex } p = p->nextarc; } } void DFSTraverse(ALGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 DFS(G, i); //从节点i开始深度优先遍历 } } } ``` 广度优先遍历: 1. 定义一个队列,将起始节点入队。 2. 当队列不为空时,取出队首节点,访问该节点,并将其未被访问的邻居节点入队。 3. 标记已访问的节点。 4. 重复步骤2和3,直到队列为空。 邻接表实现广度优先遍历的代码: ```c #define MAX_VERTEX_NUM 100 //最大顶点数 typedef struct ArcNode { //边表节点 int adjvex; //邻接点在顶点表中的位置 struct ArcNode *nextarc; //指向下一个边表节点 } ArcNode; typedef struct VNode { //顶点表节点 int data; //顶点数据 ArcNode *firstarc; //指向第一个边表节点 } VNode, AdjList[MAX_VERTEX_NUM]; typedef struct { AdjList vertices; //邻接表 int vexnum, arcnum; //的当前顶点数和弧数 } ALGraph; int visited[MAX_VERTEX_NUM]; //标记节点是否被访问过 void BFS(ALGraph G, int v) { int queue[MAX_VERTEX_NUM]; //定义队列 int front = , rear = ; //队首和队尾指针 visited[v] = 1; //标记节点v已被访问 printf("%d ", G.vertices[v].data); //访问节点v queue[rear++] = v; //将节点v入队 while (front != rear) { //队列不为空时 int w = queue[front++]; //取出队首节点w ArcNode *p = G.vertices[w].firstarc; while (p) { if (!visited[p->adjvex]) { //如果节点p->adjvex未被访问 visited[p->adjvex] = 1; //标记节点p->adjvex已被访问 printf("%d ", G.vertices[p->adjvex].data); //访问节点p->adjvex queue[rear++] = p->adjvex; //将节点p->adjvex入队 } p = p->nextarc; } } } void BFSTraverse(ALGraph G) { for (int i = ; i < G.vexnum; i++) { visited[i] = ; //初始化visited数组 } for (int i = ; i < G.vexnum; i++) { if (!visited[i]) { //如果节点i未被访问 BFS(G, i); //从节点i开始广度优先遍历 } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值