二十三、图的广度优先遍历

本文介绍了如何使用C++实现无向图的邻接表结构,并进行广度优先遍历。首先,通过输入的顶点序列和边序列构建邻接表,然后利用队列进行广度优先遍历,输出遍历序列。在构建邻接表时,每个节点包含一个边表头结点、连接的结点数和标记位,无向图的边需要双向建立。最后,程序展示了一个具体的例子和其输出结果。
摘要由CSDN通过智能技术生成

二十三、图的广度优先遍历

题目描述

程序的输入是无向图的顶点序列和边序列(顶点序列以*为结束标志,边序列以-1,-1为结束标志)。程序的输出为图的邻接表和广度优先遍历序列。例如:

程序输入为:
a
b
c
d
e
f
*
0,1
0,4
1,4
1,5
2,3
2,5
3,5
-1,-1

程序的输出为:
the ALGraph is
a 4 1
b 5 4 0
c 5 3
d 5 2
e 1 0
f 3 2 1
the Breadth-First-Seacrh list:aebfdc

测试输入期待的输出时间限制内存限制额外进程
测试用例 1a
b
c
d
e
f
*
0,1
0,4
1,4
1,5
2,3
2,5
3,5
-1,-1
the ALGraph is
a 4 1
b 5 4 0
c 5 3
d 5 2
e 1 0
f 3 2 1
the Breadth-First-Seacrh list:aebfdc
1秒64M0

解题思路

用一个 node 结构来模拟邻接表,data表示边表的头结点(头结点可能不止一个字符,最好用字符数组),num表示该边表中依附了几个结点,list[] 数组存储依附的结点编号,map[] 数组模拟顶点表,这样一个邻接表就模拟出来了。

同时,因为我们在之后还要进行广度优先遍历,所以还需要添加一个标记位 vis,来检测当前结点是否被标记过。

struct node
{
    char data[10];		//边表头结点
    int list[100];		//边表中各个结点编号
    int num;			//边表中连接的结点数
    int vis;			//标记位
}map[100];				//顶点表

一点值得注意的是,本题输入的是无向图,所以对于一条输入的边序列(x,y),我们需要建立两条边。

map[x].list[map[x].num] = y;
map[x].num++;
map[y].list[map[y].num] = x;
map[y].num++;

当我们用 bfs 遍历求解时,为了避免多次重复遍历,用一个 for 循环,判断结点的 vis 不为 0,则跳过该结点的遍历。

上机代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
	char data[10];//边表头结点
	int list[100];//边表中各个结点编号
	int num;	  //边表中连接的结点数
	int vis;	  //标记位
}map[100];		  //顶点表
int counts = 0, x, y;

void bfs(int n)
{
	queue<int>q;
	int ans = n;
	int tmp;
	map[ans].vis = 1;
	q.push(ans);
	while (!q.empty())
	{
		ans = q.front();
		q.pop();
		printf("%c", map[ans].data[0]);
		if (map[ans].num == 0)
			continue;
		for (int k = map[ans].num - 1; k >= 0; k--)
		{
			tmp = map[ans].list[k];
			if (map[tmp].vis == 1)
				continue;
			q.push(tmp);
			map[tmp].vis = 1;
		}
	}
}
int main()
{
	while (~scanf("%s",&map[counts].data))//输入节点
	{
		if (map[counts].data[0] == '*')
			break;
		counts++;
	}
	while (~scanf("%d,%d", &x, &y))//输入邻接表
	{
		if (x == -1 && y == -1)//结束标志
			break;
		//无向图需要建立两条边
		map[x].list[map[x].num] = y;
		map[x].num++;
		map[y].list[map[y].num] = x;
		map[y].num++;
	}
	printf("the ALGraph is\n");
	for (int i = 0; i < counts; i++)//打印邻接表
	{
		printf("%c", map[i].data[0]);
		for (int j = map[i].num - 1; j >= 0; j--)
		{
			printf(" %d", map[i].list[j]);
		}
		printf("\n");
	}
	printf("the Breadth-First-Seacrh list:");
	for (int i = 0; i < counts; i++)//bfs序列
	{
		if (map[i].vis == 0)
			bfs(i);
	}
	printf("\n");
	//system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值