C++图的建立---邻接矩阵-----邻接表

news2024/11/26 2:29:01

目录

图的表示方式

 邻接矩阵

邻接表

图的遍历

深度优先遍历

深度优先遍历算法步骤: 

图的广度优先遍历 

广度优先遍历算法步骤: 

图的邻接矩阵存储来创建图

代码 

运行结果: 

 图的邻接表存储来创建图

如下图:

运行结果:


图的表示方式

  • 图的表示方式有两种:
  • 二维数组表示(邻接矩阵);链表表示(邻接表) 

 邻接矩阵

​ 邻接矩阵 邻接矩阵:邻接矩阵 是表示图形中顶点之间相邻关系的矩阵 

邻接表

  1.  邻接矩阵需要为每个顶点都分配 n 个边的空间,其实有很多边都是不存在的,会造成空间的一定损失.
  2. 邻接表的实现只关心存在的边,不关心不存在的边。因此没有空间浪费,邻接表由数组+链表组成.

图的遍历

  • 所谓图的遍历,即是对结点的访问。一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略:
  1. 深度优先遍历
  2. 广度优先遍历

深度优先遍历

  • 深度优先遍历算法步骤: 

  1. 访问初始结点 v,并标记结点 v 为已访问
  2. 查找结点 v 的第一个邻接结点 w
  3. 若 w 存在,则继续访问 4,如果 w 不存在,则回到第 1 步,将从 v 的下一个结点继续
  4. 若 w 未被访问,对 w 进行深度优先遍历递归(即把 w 当作另一个 v ,然后进行步骤 123)
  5. 查找结点 v 的 w 邻接结点的下一个邻接结点,转到步骤 3
     
  • 核心代码: 

//深度优先遍历
void MyGraph::DFSearch(int v) {
	cout << vertex[v]<<" ";
	visited[v] = 1;
	for (int i = 0; i < vertexNum; i++) {
		if (edge[v][i] == 1 && visited[i] == 0) {
			DFSearch(i);
		}
	}
}

图的广度优先遍历 

  • 图的广度优先遍历(Broad First Search)
  • 类似于一个分层搜索的过程,广度优先遍历需要使用一个队列以保持访问过的结点的顺序,以便按这个顺序来访问这些结点的邻接结点

广度优先遍历算法步骤: 

  1. 访问初始结点 v 并标记结点 v 为已访问
  2. 结点 v 入队列
  3. 当队列非空时,继续执行,否则算法结束
  4. 出队列,取得头结点 u
  5. 查找结点 u 的第一个邻接结点 w
  6. 若结点 u 的邻接结点 w 不存在,则转到步骤 3;否则循环执行以下三个步骤
  1. >>若结点 w 尚未被访问,则访问结点 w 并标记为已访问
  2. >>结点 w 入队列
  3. >>查找结点 u 的继 w 邻接结点后的下一个邻接结点 w,转到步骤6
  •  核心代码

//广度优先遍历
void MyGraph::BFSearch(int v){
	int w, j;
	int Q[MaxSize];			//采用顺序队列
	int front=-1, rear=-1;	//初始化队列
	cout << vertex[v] << " ";
	visited[v] = 1;

	Q[++rear] = v;		//被访问的顶点入队
	while (front != rear) {
		w = Q[++front];//将对头元素出队并送到v中
		for (j = 0; j < vertexNum; j++) {
			if (edge[w][j] == 1 && visited[j] == 0) {
				cout << vertex[j] << " ";
				visited[j] = 1;
				Q[++rear] = j;
			}
		}
	}
}

图的邻接矩阵存储来创建图

  • 代码 

/*
* 图的邻接矩阵存储----
*					图的建立与遍历:
*								   广度优先遍历---深度优先遍历
*/
#include<iostream>
using namespace std;

const int MaxSize = 10;

int visited[MaxSize] = { 0 };//全局变量visited初始化——遍历的标志

class MyGraph {
private:
	char vertex[MaxSize];//存放顶点的数组
	char edge[MaxSize][MaxSize];//存放边的数组
	int vertexNum;//图的顶点数
	int edgeNum;//图的边数
public:
	MyGraph(char a[], int n, int e);//传数组,顶点数,边数
	~MyGraph();
	void DFSearch(int v);//深度优先遍历
	void BFSearch(int v);//广度优先遍历
};

//图的建立
MyGraph::MyGraph(char a[], int n, int e){
	int i, j, k;
	this->vertexNum = n;	 //图的顶点数
	this->edgeNum = e;		//图的边数

	//储存顶点
	for (i = 0; i < vertexNum; i++) {
		vertex[i] = a[i];
	}

	//初始化邻接矩阵
	for (i = 0; i < vertexNum; i++) {
		for (j = 0; j < vertexNum; j++) {
			edge[i][j] = 0;
		}
	}

	cout << "请输入边依附的两个顶点的编号:" << endl;

	// 依次输入每一条边----无向图---对称,有向图--可能不对称
	for (k = 0; k < edgeNum; k++) {
		cin >> i >> j;			//输入边依附的两个顶点的编号
		//无向图-- - 对称---有i j必有j i
		edge[i][j] = 1; edge[j][i] = 1;		//置有边标志为1,没有默认为0
	}
}

//图的析构——图的邻接矩阵存储为静态存储分配,
//在图变量退出作用域时自动释放所占内存单元,因此,
//图的邻接矩阵存储无须销毁,析构函数为空
MyGraph::~MyGraph(){}

//深度优先遍历
void MyGraph::DFSearch(int v) {
	cout << vertex[v]<<" ";
	visited[v] = 1;
	for (int i = 0; i < vertexNum; i++) {
		if (edge[v][i] == 1 && visited[i] == 0) {
			DFSearch(i);
		}
	}
}

//广度优先遍历
void MyGraph::BFSearch(int v){
	int w, j;
	int Q[MaxSize];			//采用顺序队列
	int front=-1, rear=-1;	//初始化队列
	cout << vertex[v] << " ";
	visited[v] = 1;

	Q[++rear] = v;		//被访问的顶点入队
	while (front != rear) {
		w = Q[++front];//将对头元素出队并送到v中
		for (j = 0; j < vertexNum; j++) {
			if (edge[w][j] == 1 && visited[j] == 0) {
				cout << vertex[j] << " ";
				visited[j] = 1;
				Q[++rear] = j;
			}
		}
	}
}
 
int main() {
	int i;
	char array[] = { 'A','B','C','D','E' };
	MyGraph mygraph{ array,5,6 };//建立5个顶点,6条边的无向图
	//深度优先遍历
	for (i = 0; i < MaxSize; i++) {
		visited[i] = 0;
	}
	cout << "深度优先遍历序列为:";
	mygraph.DFSearch(0);		//从顶点0出发进行深度优先遍历
	cout << endl;

	//广度优先遍历
	for (i = 0; i < MaxSize;i++) {
		visited[i] = 0;
	}
	cout << "广度优先遍历序列为:";
	mygraph.BFSearch(0);		//从顶点0出发进行广度优先遍历

	return 0;
}

建立如下的无向图:

 

运行结果: 

 图的邻接表存储来创建图

/*
* 图的邻接表存储----
*					图的建立与遍历:
*								   广度优先遍历---深度优先遍历
*/
#include<iostream>
using namespace std;

const int MaxSize = 10;

int visited[MaxSize] = { 0 };//全局变量visited初始化——遍历的标志

//定义边表结点
struct EdgeNode
{
	int adjvex;  //邻接点数据域
	EdgeNode* next;//邻接点指针域
};

//定义顶点表结点
struct VertexNode
{
	char vertex;
	EdgeNode* firstEdge;
};

class ALGraph
{
private:
	VertexNode adjlist[MaxSize]; //存放顶点表的数组
	int vertexNum;				//图的顶点数
	int edgeNum;			   //图的边数
public:
	ALGraph(char a[], int n, int e);
	~ALGraph();
	void DFSearch(int v);//深度优先遍历
	void BFSearch(int v);//广度优先遍历
};

//有向图邻接表存储的构造函数
ALGraph::ALGraph(char a[], int n, int e){
	int i, j, k;
	EdgeNode* s = nullptr;
	this->vertexNum = n;
	this->edgeNum = e;

	//输入顶点信息,初始化顶点表
	for (i = 0; i < vertexNum; i++) {
		adjlist[i].vertex = a[i];
		adjlist[i].firstEdge = nullptr;
	}

	cout << "请输入边依附的两个顶点的编号:"<<endl;
	//依次输入每条边
	for (k = 0; k < edgeNum; k++) {
		cin >> i >> j;				//输入边依附的两个顶点的编号
		s = new EdgeNode;//生成一个边表结点s
		s->adjvex = j;
		s->next = adjlist[i].firstEdge;//将结点s插入表头
		adjlist[i].firstEdge = s;
	}
}

//图的销毁
ALGraph::~ALGraph(){
	EdgeNode* p = nullptr, * q = nullptr;
	for (int i = 0; i < vertexNum; i++) {
		p = q = adjlist[i].firstEdge;
		while (p != nullptr) {
			p = q->next;
			delete q;
			q = p;
		}
	}
}

//深度优先遍历
void ALGraph::DFSearch(int v) {
	int j;
	EdgeNode* p = nullptr;
	cout << adjlist[v].vertex; visited[v] = 1;
	p = adjlist[v].firstEdge;//工作指针p指向顶点v的边表

	while (p != nullptr) {
		j=p->adjvex;
		if (visited[j] == 0) {
			DFSearch(j);
		}
		p = p->next;
	}
}


//广度优先遍历
void ALGraph::BFSearch(int v) {
	int w, j;
	int Q[MaxSize];			//采用顺序队列
	int front = -1, rear = -1;	//初始化队列
	EdgeNode* p = nullptr;
	cout << adjlist[v].vertex<<" ";
	visited[v] = 1;
	Q[++rear] = v;				 //被访问的顶点入队

	while (front != rear) {		//当队非空时
		w = Q[++front];
		p = adjlist[w].firstEdge;//工作指针p指向顶点v的边表
		while (p!=nullptr){
			j = p->adjvex;
			if (visited[j] == 0) {
				cout << adjlist[j].vertex << " ";
				visited[j] = 1;
				Q[++rear] = j;
			}
			p = p->next;
		}
	}
}

int main() {
	char array[] = { 'A','B','C','D','E' };;
	int i;
	ALGraph algraph{ array,5,6 };//建立5个顶点,6条边的无向图

	//深度优先遍历
	for (i = 0; i < MaxSize; i++) {
		visited[i] = 0;
	}
	cout << "深度优先遍历序列为:";
	algraph.DFSearch(0);		//从顶点0出发进行深度优先遍历
	cout << endl;

	//广度优先遍历
	for (i = 0; i < MaxSize; i++) {
		visited[i] = 0;
	}
	cout << "广度优先遍历序列为:";
	algraph.BFSearch(0);		//从顶点0出发进行广度优先遍历

	return 0;
}

如下图:

运行结果:

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/4396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

认定能源管理体系的条件

能源管理体系认证申请清单&#xff08;GB/T 23331-2012《能源管理体系 要求》国家标准&#xff09;体系运行时间超过6个月 1、营业执照复印件&#xff1b; 2、组织机构代码证&#xff08;适用时&#xff09;&#xff1b; 3、生产许可证和其他行政许可证明复印件、资质证明等…

保卫城市消费券安全,从这些做起

近日&#xff0c;顶象发布的《城市消费券安全调研报告》&#xff08;以下简称《调研报告》&#xff09;中明确提出&#xff0c;自消费券发放之日起&#xff0c;黑灰产便盯上了这块蛋糕。据不完全统计&#xff0c;190多亿的消费券&#xff0c;消费者只抢到29%。 而在百度键入消…

公众号网课答案在线查搭建

公众号网课答案在线查搭建 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&#…

操作系统实验三虚拟存储器管理之模拟页面置换算法(FIFOLRU)

文章目录 一、概述 &#xff08;1&#xff09;置换算法 &#xff08;2&#xff09;缺页率与命中率 二、先进先出置换算法&#xff08;FIFO&#xff09; (1)定义 (2)示例 &#xff08;3&#xff09;Belady异常 三、最近最久未使用置换算法&#xff08;LRU&#xff09; &#…

LeetCode每日一题——764. 最大加号标志

LeetCode每日一题系列 题目&#xff1a;764. 最大加号标志 难度&#xff1a;普通 文章目录LeetCode每日一题系列题目示例思路题解题目 在一个 n x n 的矩阵 grid 中&#xff0c;除了在数组 mines 中给出的元素为 0&#xff0c;其他每个元素都为 1。mines[i] [xi, yi]表示 g…

谈谈HTTP协议的方法里,GET和POST的区别?我来教你如何回答~

目录 前言 一、什么是GET、POST&#xff1f; 1.1GET 1.2POST 二、如何轻松回答&#xff1f; 第一步、直接盖棺定论&#xff1a; 第二步、谈细节上的区别&#xff1a; 前言 要想回答好这个问题&#xff0c;咱们先来了解以下什么是GET、POST方法&#xff0c;有哪些细节要注…

阿宇wifi球机如何连接手机

首先下载APP&#xff0c;请见以下三种方式&#xff1a; &#xff08;1&#xff09;至APP Store、各大应用市场搜索 “智U”&#xff0c;下载并安装APP。  &#xff08;2&#xff09;登录ezcloud.uniview.com官网&#xff0c;扫描界面右下方智U APP二维码&#xff0c;下载并…

SpringBoot线上服务假死解决,CPU内存正常

背景 开发小伙伴都知道线上服务挂掉&#xff0c;基本都是因为cpu或者内存不足&#xff0c;出现GC频繁OOM之类的情况。本篇文章区别以上的情况给小伙伴们 带来不一样的服务挂掉。 还记得哔哩哔哩713事故中那场诡计多端的0吗&#xff1f; 对就是这个0&#xff0c;和本次事故没关…

Python基础知识入门(二)

Python基础知识入门&#xff08;一&#xff09; 一、数字类型 Python 数字数据类型用于存储数值。数据类型是不允许改变的&#xff0c;如改变数字数据类型的值&#xff0c;将重新分配内存空间。 1.数字函数 函数 描述 abs(x) 返回数字的绝对值。如abs(-10) 返回 10。 fa…

前端小游戏——推箱子

最近刚刚更新完了HTML&#xff0c;CSS的万字总结&#xff0c;有很多人已经学习完了文章&#xff0c;感觉反馈还不错&#xff0c;今天&#xff0c;用HTML&#xff0c;CSS&#xff0c;JS的知识编写了一个童年经典游戏 - 推箱子&#xff0c;供学习参考。 推荐学习专栏&#xff1a…

EdrawMax Ultimate v12.0 图表和流程图

EDraw Max 是一个多合一的应用程序&#xff0c;用作演示构建器、图表创建者、可视化业务规划师和协作空间&#xff08;用于快速共享图表和模型并接收反馈&#xff09;。 该软件可用于哪些潜在用途&#xff1f; 任何人都可以从 EDraw Max 中受益。它所针对的主题和感兴趣的领域…

【EasyRL学习笔记】第十一章 模仿学习

文章目录一、前言二、行为克隆三、逆强化学习四、第三人称视角模仿学习五、序列生成和聊天机器人六、关键词总结七、习题一、前言 模仿学习 (imitation learning&#xff0c;IL) 讨论的问题是&#xff0c;假设我们连奖励都没有&#xff0c;要怎么进行更新以及让智能体与环境交…

黑马学Docker(二)

目录&#xff1a; &#xff08;1&#xff09;容器命令介绍 &#xff08;2&#xff09; 容器命令案例1 &#xff08;3&#xff09;容器命令案例2 &#xff08;4&#xff09;容器命令练习 &#xff08;5&#xff09;数据卷命令 &#xff08;6&#xff09; 数据卷挂在案例1 …

数字孪生:实现保险行业数字化转型

现如今&#xff0c;数据分析在各个行业都在广泛的使用&#xff0c;保险行业也不例外。在数字化浪潮席卷全球的时代&#xff0c;如何利用数字化技术驱动业务增长&#xff0c;实现数字化转型&#xff0c;是目前保险行业需要思考的问题。 可视化技术能够助力保险机构更好地解决互联…

[hive]维度模型分类:星型模型,雪花模型,星座模型|范式|纬度建模|数仓分层

数仓&#xff08;十八&#xff09;数仓建模以及分层总结(ODS、DIM、DWD、DWS、DWT、ADS层) - 墨天轮 一、维度模型分类:星型模型,雪花模型,星座模型 1、星型模型 星型模型中只有一张事实表&#xff0c;以及0张或多张维度表&#xff0c;事实与纬度表通过主键外键相关联&#…

vue项目 API接口封装

vue项目 API接口封装 01.基础配置创建 分别创建如下文件和文件夹 Object │ .env.development │ .env.production └─src├─api│ index.js│ login.js├─utils│ request.js.env.development 和 .env.production 配置生产环境和开发环境移步&#xf…

Java程序员不得不会的124道面试题(含答案)

1&#xff09;Java 中能创建 volatile 数组吗&#xff1f; 能&#xff0c;Java 中可以创建 volatile 类型数组&#xff0c;不过只是一个指向数组的引用&#xff0c;而不是整个数组。我的意思是&#xff0c;如果改变引用指向的数组&#xff0c;将会受到 volatile 的保护&#x…

多线程常见锁的策略

文章目录前言一、乐观锁和悲观锁1.1 定义1.2 生动有趣滴例子1.3 版本号机制二、读写锁2.1 读写锁的由来2.2 生动有趣de例子2.3 ReentrantReadWriteLock 类三、重量级锁与轻量级锁3.1 定义3.2 生动活泼の例子3.3 自旋锁&#xff08;Spin Lock&#xff09;四、公平锁与非公平锁五…

一名程序员的电脑桌面

配置&#xff1a; 酷呆桌面注册表隐藏快捷方式箭头图标开启桌面模式自动隐藏任务栏 酷呆桌面 在选择酷呆之前&#xff0c;一直是使用的Fences&#xff0c;他的桌面切换功能非常赞&#xff0c;适合划分工作区。但由于强迫症实在是忍受不了肉眼可见的掉帧、黑背景bug&#xff0…

简简单单搞一个实用的Android端搜索框

Hello啊老铁们&#xff0c;今天带来一个非常实用的自定义搜索框&#xff0c;包含了搜索框、热门搜索列表、最近搜索列表等常见的功能&#xff0c;有类似的&#xff0c;大家可以直接复用&#xff0c;将会大大节约您的开发时间&#xff0c;有一点&#xff0c;很负责任的告诉大家&…