【数据结构】实验十 图的遍历

实验内容:
使用邻接矩阵或链接表来存储图,并编程实现DFS和BFS算法。

#include<iostream>
using namespace std;
#define MaxInt 32767    // 极大值 ∞
#define MVNum 100       // 最大顶点数
#define MAXSIZE 100     // 队列的最大长度

bool visit_DFS[MVNum] = { false }; // 定义一个DFS访问数组 并初始化为false(代表被访问过)
bool visit_BFS[MVNum] = { false }; // 定义一个BFS访问数组 并初始化为false(代表被访问过)

typedef char VerTexType; // 假设顶点的数据类型为字符型
typedef int ArcType; // 假设边的权值类型为整型
typedef struct
{
	VerTexType vexs[MVNum]; // 顶点表
	ArcType arcs[MVNum][MVNum]; // 邻接矩阵
	int vexnum, arcnum; // 图的当前点数和边数
}AMGraph;

typedef struct // 定义队列的结构体
{
	VerTexType* base; // 存储队列内元素 元素类型为Person
	int front; // 头指针 始终指向队列首元素
	int rear; // 尾指针 始终指向队列尾元素
}SqQueue;

void InitQueue(SqQueue& Q)// 队列的初始化
{
	Q.base = new VerTexType[MAXSIZE];
	if (!Q.base)
		exit(1);
	Q.front = Q.rear = 0; // 将队列头指针和尾指针置为0 此时队列为空
}

void EnQueue(SqQueue& Q, int e) // 在队尾插入元素 e
{
	if ((Q.rear + 1) % MAXSIZE == Q.front) // 队列已满
		return;
	Q.base[Q.rear] = e; // 尾指针始终指向队列尾元素的下一个元素
	Q.rear = (Q.rear + 1) % MAXSIZE; // 赋值完成后 尾指针加1
}

void DeQueue(SqQueue& Q, int& e) // 删除Q的队头元素,用e返回其值
{
	if (Q.front == Q.rear) // 判断是否队空
		return;
	e = Q.base[Q.front]; // 保存队头元素
	Q.front = (Q.front + 1) % MAXSIZE; // 队头指针加1
}

bool EmptyQueue(SqQueue Q) // 判断是否是空队列
{
	if (Q.front == Q.rear) // 空队列
	{
		return true;
	}
	else // 非空队列
	{
		return false;
	}
}

int LocateVex(AMGraph G, VerTexType v) // 返回顶点数组的下标
{
	for (int i = 0; i < G.arcnum; i++)
		if (G.vexs[i] == v)
			return i;
	return -1; // 未找到顶点时 返回-1
}

void CreateUDN(AMGraph& G) // 采用邻接矩阵表示法创建无向图
{
	cout << "请输入总顶点数和边数(以空格分隔开): ";
	cin >> G.vexnum >> G.arcnum;
	cout << "请依次输入各个点的信息: ";
	for (int i = 0; i < G.vexnum; i++) // 依次输入点的信息
		cin >> G.vexs[i];
	for (int i = 0; i < G.vexnum; i++) // 初始化邻接矩阵
		for (int j = 0; j < G.vexnum; j++)
			if (i == j) // 主对角线的元素值 置为0
				G.arcs[i][j] = 0;
			else // 边的权值置为最大值MaxInt
				G.arcs[i][j] = MaxInt;
	VerTexType v1, v2;
	ArcType w;
	for (int k = 0; k < G.arcnum; k++) // 构造邻接矩阵
	{
		cout << "请依次输入一条边依附的两个顶点及权值: ";
		cin >> v1 >> v2 >> w; // 输入一条边依附的顶点及权值
		int i = LocateVex(G, v1); // 确定v1在G中的位置(顶点数组的下标)
		int j = LocateVex(G, v2); // 确定v2在G中的位置(顶点数组的下标)
		if (i == -1 || j == -1) // 判断是否成功赋值 即是否存在输入的顶点
		{
			cout << "不存在输入顶点!" << endl;
			k--; // 遍历次数减一
			continue; // 直接进行下次循环
		}
		G.arcs[i][j] = w; // 边<v1,v2>的权值置为w
		G.arcs[j][i] = G.arcs[i][j]; // 边<v2,v1>的权值置为w
	}
}

void OutPut_LinJie(AMGraph G) // 输出邻接矩阵
{
	cout << "\t";
	for (int i = 0; i < G.vexnum; i++) // 输出第一行 -> 各个点的信息
		cout << G.vexs[i] << "\t";
	cout << endl;
	for (int i = 0; i < G.vexnum; i++) // 依次输出每一行各个点的信息(顶点信息 权值)
	{
		cout << G.vexs[i] << "\t";
		for (int j = 0; j < G.vexnum; j++)
			cout << G.arcs[i][j] << "\t";
		cout << endl;
	}
}

void DFS_AM(AMGraph G, int v) // 深度优先搜索
{
	cout << G.vexs[v]; // 访问第v个顶点
	visit_DFS[v] = true; // 将第v个顶点的标志数组的相应分量值置为true
	for (int w = 0; w < G.vexnum; w++) // 依次检查v的所有邻接点
	{
		if ((G.arcs[v][w] != MaxInt) && (!visit_DFS[w]))
		{ // 邻接点有值 且没被访问时
			cout << " -> ";
			DFS_AM(G, w); // 递归调用DFS
		}
	}
}

int FirstAdjVex(AMGraph G, int u) // 查找u的第一个邻接点 返回其下标
{
	for (int i = 0; i < G.vexnum; i++)
		if (G.arcs[u][i] != MaxInt)
			return i;
	return -1; // 未查找到 返回-1
}

int NextAdjVex(AMGraph G, int u, int w) // 查找u的第一个没被访问的邻接点
{
	for (int i = 0; i < G.vexnum; i++)
		if ((G.arcs[u][i] != MaxInt) && (!visit_BFS[i]))
			return i; // 返回其下标
	return -1; // 未查找到 返回-1
}

void BFS_AM(AMGraph G, int v) // 广度优先搜索
{
	cout << G.vexs[v]; // 访问第v个顶点
	visit_BFS[v] = true; // 将其访问标志数组的相应分量置为true
	SqQueue Q; // 定义一个队列
	InitQueue(Q); // 初始化定义的队列
	EnQueue(Q, v); // 第v个顶点进队
	while (!EmptyQueue(Q)) // 队列非空 执行循环条件
	{
		int u; // 定义u 存储顶点的下标
		DeQueue(Q, u); // 队首元素出队 赋值给u
		for (int w = FirstAdjVex(G, u); w >= 0 && w < G.vexnum; w = NextAdjVex(G, u, w))
		{// 从u的第一个邻接点遍历到最后一个邻接点
			if (!visit_BFS[w]) // 判断邻接点是否被访问过
			{// 没有被访问过 
				cout << " -> " << G.vexs[w]; // 访问该顶点
				visit_BFS[w] = true; // 并将标志数组的相应分量值置为true
				EnQueue(Q, w); // w进队
			}
		}
	}
}

int main()
{
	AMGraph G; // 定义一个邻接矩阵
	int t; // 临时记录查找开始位置
	CreateUDN(G); // 创建一个邻接矩阵 存储图的信息
	OutPut_LinJie(G); // 输出邻接矩阵
	cout << "请输入DFS的查找开始位置: ";
	cin >> t;
	cout << "DFS: ";
	DFS_AM(G, t - 1); // 深度优先搜索
	cout << endl;
	cout << "请输入BFS的查找开始位置: ";
	cin >> t;
	cout << "BFS: ";
	BFS_AM(G, t - 1); // 广度优先搜素
	cout << endl;
	system("pause");
	return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张鱼·小丸子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值