2020考研-王道数据结构-图-图的遍历

说在开头

  1. 某些语法采用的是c11标准。
  2. 博客中中的代码均为可执行程序,以函数的形式给出,最后所有的程序会在博客完结后上传到CSDN。

头文件定义

#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>

数据结构定义

#define MaxVertexNum 100	// 图中顶点数目的最大值

typedef int InfoType;		// 边权信息
typedef int VertexType;		// 顶点信息

typedef struct ArcNode{		// 边表结点 
	int adjvex;				// 该弧指向的顶点的位置
	struct ArcNode *next;	// 指向下一条弧的指针
	InfoType info;			// 网的边权值

	ArcNode(){ next = NULL; info = 0; };
	ArcNode(int aj, InfoType io, ArcNode* p = NULL){ adjvex = aj; info = io; next = p; };

}ArcNode;					

typedef struct VNode{		// 顶点表结点
	VertexType data;		// 顶点信息
	ArcNode *first;			// 指向第一条依附该顶点的弧的指针

	VNode(){ first = NULL; data = 0; }

}VNode, AdjList[MaxVertexNum];

typedef struct{	
	AdjList vertices;		// 邻接表
	int vexnum, arcnum;		// 图的顶点数和弧数
}ALGraph;					// ALGraph是以邻接表存储的图的类型

测试点数据

测试数据1
5 7
1 2 1
1 5 1
2 5 1
5 4 1
2 3 1
2 4 1
3 4 1

测试数据2
7 6
1 2 1
1 3 1
2 6 1
2 5 1
3 4 1
3 7 1

辅助函数-建图

// 通过输入信息创建一个 无向图
ALGraph creatGraph()
{
	ALGraph gra;
	int vn, an;
	cout << "输入图的顶点数和边数:" << endl;
	cin >> vn >> an;
	gra.vexnum = vn;
	gra.arcnum = an;
	cout << "输入 x y z:表示 从顶点x到顶点y的权值是z:" << endl;
	for (int i = 0, x, y, z; i < an; i++)
	{
		cin >> x >> y >> z;
		ArcNode* p = gra.vertices[x].first;
		gra.vertices[x].first = new ArcNode(y, z, p);
		p = gra.vertices[y].first;
		gra.vertices[y].first = new ArcNode(x, z, p);
	}

	return gra;
}

P206 第二题

题目描述

判断一个无向图G是不是一棵树,是返回True,否则返回false。

题目分析

判断的话比较好判断:
不存在环的图就是一棵树。
是一个连通图并且图中边的个数比顶点个数少一个就是树。

对于判环操作,可以用并查集也可以用专门判断环的算法。相对而言第二种算法对于无向图的判断比较容易写代码,只需要遍历整个图记录下来图中的顶点和边信息即可判断。

代码
// 判断图是不是一棵树辅助程序
void dfs(ALGraph &gra,int v, int *vis, int &vcnt, int &ecnt)
{
	if (vis[v]){ return; }
	vis[v] = 1;
	vcnt++;
	
	//cout << v << " ";

	ArcNode *list = gra.vertices[v].first;
	while (list)
	{
		ecnt++;
		dfs(gra, list->adjvex, vis, vcnt, ecnt);
		list = list->next;
	}
	return;
}

// 判断图是不是一棵树
bool isTree(ALGraph gra)
{
	int vis[MaxVertexNum];
	memset(vis, 0, sizeof(vis));
	int ecnt = 0, vcnt = 0;
	dfs(gra, 1, vis, vcnt, ecnt);
	if (vcnt == gra.vexnum && ecnt == 2 * (gra.vexnum - 1))
		return true;
	return false;
}

P206 第三题

题目描述

写出图的DFS算法的非递归算法,图采用邻接表的形式存储。

题目分析

DFS(深度搜索)采用栈。
BFS(广度搜索)采用队列。

代码
// 深度搜索遍历整棵树
void dfsGraph(ALGraph gra)
{
	if (gra.vexnum == 0) return;
	stack<int> stk;
	int vis[MaxVertexNum];
	memset(vis, 0, sizeof(vis));
	stk.push(1);
	while (stk.size())
	{
		int nv = stk.top();
		stk.pop();
		if (vis[nv]) continue;
		vis[nv] = 1;
		
		cout << nv << endl;   // 对节点进行访问操作
		
		auto list = gra.vertices[nv].first;
		while (list)
		{
			stk.push(list->adjvex);
			list = list->next;
		}
	}
}

P206第四题

题目描述

分别采用基于深度优先遍历和广度优先遍历算法判断以邻接表方式存储的图中是否存在由顶点vi到顶点vj的路径。

代码
// 判断从a到b是否存在路径 深度优先
bool canAtoB_dfs(ALGraph gra, int a, int b)
{
	if (a <= 0 || b <= 0 || a > gra.vexnum || b > gra.vexnum){
		cerr << "输入的顶点不符合要求" << endl;
		return false;
	}
	stack<int> stk;
	stk.push(a);
	int vis[MaxVertexNum];
	memset(vis, 0, sizeof(vis));
	while (stk.size())
	{
		int nv = stk.top();
		stk.pop();
		if (nv == b)return true;
		if (vis[nv]) continue;
		vis[nv] = 1;
		auto list = gra.vertices[nv].first;
		while (list)
		{
			stk.push(list->adjvex);
			list = list->next;
		}
	}
	return false;
}

// 判断从a到b是否存在路径 广度优先
bool canAtoB_bfs(ALGraph gra, int a, int b)
{
	if (a <= 0 || b <= 0 || a > gra.vexnum || b > gra.vexnum)
	{
		cerr << "输入的顶点越界" << endl;
		return false;
	}
	int vis[MaxVertexNum];
	memset(vis, 0, sizeof(vis));
	queue<int> que;
	que.push(a);
	while (que.size())
	{
		int nv = que.front();
		que.pop();
		if (nv == b) return true;
		if (vis[nv]) continue;
		vis[nv] = 1;
		auto list = gra.vertices[nv].first;
		while (list)
		{
			que.push(list->adjvex);
			list = list->next;
		}
	}
	return false;
}

P206第五题

题目描述

输出所有从顶点Vi到顶点Vj的简单路径。
简单路径:序列中顶点不重复的路径。

代码
// 打印图中所有从a到b的简单路径
// 简单路径:序列中顶点不重复的路径 深度搜索寻找路径
vector< vector<int> > dfs(ALGraph gra, int a, int b, vector<int> &path)
{
	static vector<vector<int>> paths;
	static int vis[MaxVertexNum] = { 0 };
	//for (int i = 0; i < MaxVertexNum; i++)
	//	cout << vis[i] << " ";
	//cout << endl;
	//return vector<vector<int>>();

	if (a <= 0 || a > gra.vexnum || b <= 0 || b > gra.vexnum) {
		cerr << "输入的顶点格式不正确" << endl;
		return vector<vector<int>>();
	}

	if (a == b){
		path.push_back(b);
		paths.push_back(path);
		path.pop_back();
		return vector<vector<int>>();
	}
	auto list = gra.vertices[a].first;
	path.push_back(a);
	vis[a] = 1;
	while (list)
	{
		if(!vis[list->adjvex]) dfs(gra, list->adjvex, b, path);
		list = list->next;
	}
	path.pop_back();
	vis[a] = 0;
	return paths;
}


// 打印所有从A到B的简单路径 辅助程序
void printPathsFromAtoB(ALGraph gra, int a, int b)
{
	vector<int> path;
	vector<vector<int>> paths;
	paths = dfs(gra, a, b, path);
	
	for (int i = 0; i < paths.size(); i++)
	{
		cout << "路径 " << i << " :";
		for (int j = 0; j < paths[i].size(); j++)
		{
			cout << paths[i][j] << " ";
		}
		cout << endl;
	}
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值