BFS--广度优先搜索--图的邻接表

本文详细介绍了如何使用邻接链表结构来构建图,并通过广度优先搜索算法来遍历图中的节点。文章包括图的初始化、顶点和边的添加、图的创建和输出,以及广度优先搜索的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# include <stdio.h>
# include <malloc.h>
# include <memory.h>

# define MAX 20			//顶点最大值 

typedef struct ARCNODE
{
	int num;			//该边所指的顶点的位置 
	struct ARCNODE *next;		//指向下一条边的指针 
}arcnode;		//表的结点 

typedef struct VNODE
{	
	char data;		//顶点信息 
	arcnode *firstarc;		//指向第一条依附该顶点的边的弧指针 
}adjlist[MAX];		//头结点 

typedef struct
{
	adjlist vertices;
	bool visited[MAX];		//访问标志数组 
	int arcnum,vexnum;		//图的顶点数和弧数 
}mgraph;

void init_mgraph(mgraph &g)		//初始化图 
{
	memset(g.visited,false,sizeof(bool)*MAX);		//访问标志数组为false时,未访问 
	g.vexnum = 0;
	g.arcnum = 0;
}

int locatevex(mgraph &g,char ch)		//定位顶点ch在顶点向量中的位置 
{
	int i;
	for (i=0; i<g.vexnum && ch != g.vertices[i].data; ++i)
	;
	if (i >= g.vexnum)
	return -1;
	
	return i;
}

void add_vex(mgraph &g)		//增加顶点 
{
	printf ("请输入顶点个数\n");
	scanf ("%d",&g.vexnum);
	printf ("请输入顶点信息\n");
	for (int i=0; i<g.vexnum; ++i)
	{
		scanf (" %c",&g.vertices[i].data);		//构造结点向量 
		g.vertices[i].firstarc = NULL;
	}
}

void add_arc(mgraph &g)		//增加边 
{
	arcnode *s,*t;
	printf ("输入边的个数\n");
	scanf (" %d",&g.arcnum);
	char ch1,ch2;
	printf ("请输入边的信息\n");
	for (int k=0; k<g.arcnum; ++k)
	{
		scanf (" %c %c",&ch1,&ch2);
		int i = locatevex(g,ch1);
		int j = locatevex(g,ch2);		//定义ch1,ch2在顶点向量的位置 
		s = (arcnode *)malloc(sizeof(ARCNODE));
		t = (arcnode *)malloc(sizeof(ARCNODE));		
		
		s->num = j;		//该边所指向的顶点的位置为j
		s->next = g.vertices[i].firstarc;
		g.vertices[i].firstarc = s;
		
		t->num = i;		//该边所指向的顶点的位置为i 
		t->next = g.vertices[j].firstarc;
		g.vertices[j].firstarc = t;
	}
}

void creat_mgraph(mgraph &g)		//构造邻接链表 
{
	add_vex(g);
	add_arc(g);
}

void print_mgraph(mgraph &g)		//输出图 
{
	int i;
	arcnode *p;
	printf("编号		顶点			邻接顶点\n");
	for (i=0; i<g.vexnum; ++i)
	{
		printf (" %d		%c			",i,g.vertices[i].data);
		for (p=g.vertices[i].firstarc; p; p=p->next)
		{
			printf ("%d ",p->num);
		}
		printf ("\n");
	}
}

void visit(mgraph &g,int i)
{
	printf ("%c ",g.vertices[i].data);
	g.visited[i] = true;		//以访问 
}

void BFStraverse(mgraph &g,int i)		//广度优先搜索 
{										//从i结点可是搜索 
	arcnode *p;	
	int quene[MAX];				//辅助数组 
	memset(quene,0,sizeof(int)*MAX);
	int front = 0;		//头指针 
	int rear = 0;		//尾指针 
	int gettop;		//取队头,标记结点位置 
	
	visit(g,i);
	quene[rear++] = i;		//入队 
	
	while (front != rear)		//队列非空 
	{
		gettop = quene[front++];	//出队 
		for (p=g.vertices[gettop].firstarc; p; p=p->next)
		{
			if (!g.visited[p->num])
			{
				visit(g,p->num);
				quene[rear++] = p->num;		//入队 
			}
		}
	}
}

int main (void)
{
	mgraph g;
	init_mgraph(g);
	creat_mgraph(g);
	print_mgraph(g);
	BFStraverse(g,0);
	
	return 0;
}

### 使用邻接表存储的进行广度优先遍历 对于基于邻接表存储结构的无向,可以利用队列来实现广度优先遍历(BFS)[^1]。此方法能够有效地探索从起始顶点出发可到达的所有其他顶点,并按照它们被发现的顺序记录下来。 #### 构建邻接表示例 假设有一个简单的无向,其顶点集合为{A, B, C, D},边集{(A,B), (B,C), (C,D)}。那么对应的邻接表形式如下: - C -> B -> D - D -> C 每条链表中的结点代表与当前顶点相连的另一个顶点;为了方便编程操作,在实际编码时通常会使用数组加指针的方式模拟上述链接关系[^2]。 #### 广度优先遍历算法伪代码 ```cpp void BFS(LGraph Graph, Vertex S, void (*Visit)(Vertex)) { // 初始化访问标记数组 bool Visited[MAX_VERTICES]; memset(Visited, false, sizeof(bool)*MAX_VERTICES); queue<Vertex> q; Visit(S); // 访问起点S Visited[S] = true; // 设置已访问标志 q.push(S); while (!q.empty()) { // 当队列不为空时循环执行 Vertex v = q.front(); // 取出队首元素v q.pop(); AdjList adjNodes = GetAdjacencyList(Graph, v); // 获取v相邻节点列表 for each w in adjNodes do{ if (!Visited[w]) { // 如果w未被访问过则处理之 Visit(w); // 对新找到的邻居w调用visit函数 Visited[w] = true; // 更新状态为已访问 q.push(w); // 将该邻居加入等待队列中以便后续继续查找它的邻居们 } } } } ``` 这段代码展示了如何通过维护一个`visited[]`布尔型数组跟踪哪些顶点已经被访问过了,从而避免重复访问同一个顶点。同时借助于标准库提供的双端队列(`queue`)实现了先进先出(FIFO)的数据存取模式,确保每次总是最先处理最早进入队列的那个顶点及其直接关联者[^3]。 #### 输出样例 考虑输入数据定义了一个由五个顶点组成的简单无向,其中包含了六条连接不同顶点之间的路径。当指定从某个特定位置开始执行广度优先搜索之后,最终得到的结果将是按层次展开的一系列顶点名称序列[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值