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

2023-11-02

目录

图的表示方式

 邻接矩阵

邻接表

图的遍历

深度优先遍历

深度优先遍历算法步骤: 

图的广度优先遍历 

广度优先遍历算法步骤: 

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

代码 

运行结果: 

 图的邻接表存储来创建图

如下图:

运行结果:


图的表示方式

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

 邻接矩阵

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

邻接表

  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;
}

如下图:

运行结果:

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++图的建立---邻接矩阵-----邻接表 的相关文章

  • 如何获取正在访问 ASP.NET 应用程序的当前用户?

    为了获取系统中当前登录的用户 我使用以下代码 string opl System Security Principal WindowsIdentity GetCurrent Name ToString 我正在开发一个 ASP NET 应用程
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 重载<<的返回值

    include
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 配置CentOS8 yum镜像源

    配置yum镜像主要修改三个文件 文件位置 etc yum repos d CentOS Linux AppStream repo 将上面的两段代码注释掉 之后添加清华镜 清华云镜像地址 baseurl https mirrors tuna
  • 【问题记录】pytorch自定义数据集 No such file or directory, invalid index of a 0-dim

    保存模型 保存整个神经网络的结构和模型参数 torch save mymodel mymodel pkl 只保存神经网络的模型参数 torch save mymodel state dict mymodel params pkl 导入模型
  • [Linux]Ubuntu下idea的idea64.vmoption文件

    换了ubuntu环境开发 动了help gt Edit custom Vm options的文件 导致idea无法打开 解决办法 删除 root config JetBrains IntelliJIdea2022 1 idea64 vmop
  • [电动智能汽车-4]:原理 - 高压电源系统与互锁系统

    目录 第1章 高压电源系统概述 1 1 高压电源系统原理图 1 2 高压电源系统连接图 1 3 互锁 第2章 动力电池 2 1 安装位置 2 2 动力电池的外观 2 3 动力电池的组成 2 4 电芯的类型 2 5 电池包的参数 2 6 高压
  • Docker的Compose规范现已成为开放标准

    由Docker创建的用于定义多容器应用程序的系统Docker Compose现在将作为开放标准进行开发 称为新标准的Compose规范旨在允许Compose创建的应用程序在Kubernetes和Amazon Elastic Containe
  • 你不知道的JavaScript----promise

    目录 什么是Promise Promise Promise 值 完成事件 Promise 事件 具有 then 方法的鸭子类型 Promise 信任问题 调用过早 调用过晚 Promise 调度技巧 回调未调用 调用次数过少或过多 未能传递
  • 正则表达式之旅_sed_awk

    谈谈正则表达式这个东西 我想作为一个程序员 正则表达式大家绝对不陌生 正则表达式好像一个有限则动机 主要作用是匹配 但是同时因为这个功能 我们可以扩展很多其他用法 像很多语言都引人了正则表达式 java C 等面向对象语言 更多的是脚本语言
  • 基于Smack3.0.4+ Openfire3.10.2开发之Android 客户端之一

    我们在之前依次介绍openfire部署以及smack常用API的使用 这一节中我们着力介绍如何基于asmack开发一个Android的客户端 本篇的重点在实践 讲解和原理环节 大家可以参考前面我所发布的OpenFire和Smack的相关文章
  • Vmware 显示“您在运行该虚拟机时启用了侧通道缓解+DevicePowerOn”启动失败+模块“VPMC”启动失败”

    一 问题描述 首先显示 您在运行该虚拟机时启用了侧通道缓解 侧通道缓解可增强安全性 但也会降低性能 要禁用缓解 请在虚拟机设置的 高级 面板中更改侧通道缓解设置 有关更多详细信息 请参阅 VMware 知识库文章 79832 网址为 htt
  • 最小(大)堆实现topK问题

    最小 大 堆实现topK问题 topK问题 即求一组数据中最大 最小 的前K个数据 一般情况下数据量都比较大 比如 班级前10名 世界500强 等级分排名等 对于topK问题 能想到的最简单直接的方式就是排序 但是 如果数据量非常大 排序就
  • Pytorch框架基础

    目录 1 02张量的简介与创建 pytorch中的Tensor 张量的创建 1 03张量的操作 1 拼接 2 张量的拼接与切分 3 张量索引 4 张量变换 1 04计算图与动态图机制 1 05自动求导和Logist回归 1 Autograd
  • wandb demo

    import wandb import random class test def init self team proj name self run wandb init entity team project proj name nam
  • Go_时间日期函数

    时间日期 func main 获取当前时间 now time Now fmt Println 当前时间 now 获取年月日时分秒 fmt Println 年 now Year fmt Println 月 int now Month 不转in
  • VMware虚拟机下安装Ubuntu16.04镜像完整教程

    目录 1 安装前准备 2 安装Ubuntu 16 04镜像 3 One More Thing 1 安装前准备 PC电脑操作系统是WIN7 已正确安装虚拟机VMware 12 2 安装Ubuntu 16 04镜像 下载Ubuntu镜像文件 下
  • 宝可梦 序列号认证服务器发生了错误,宝可梦探险寻宝无法连接服务器是什么原因...

    宝可梦探险寻宝中不少玩家反馈都会遇到宝可梦探险寻宝无法连接服务器是什么原因的问题 那么怎么解决这个问题呢 这边ourplay小编为大家分享几个解决方案 宝可梦探险寻宝游戏简介 宝可梦 探险寻宝 是任天堂在2018年5月29日推出的游戏 最初
  • 用了HBuilderX近一年,最后还是选择了VSCode

    用了HBuilderX近一年 最后还是选择了VSCode 关于前端的IDE 流行的无非也就那么几款 但若要问那款编辑器最好用 键盘侠们可能要闹翻了天 本人接触前端以来大概使用webstorm有3 4个月之久 当时webstorm好像名气比V
  • 28天自我挑战,从0开始学会Python月入25K

    28天自我挑战 从0开始学 会Python月入28K Python最近这么火 很多小伙伴还不知道Python到底是什么 能干什么 一句话 Python是最简洁 最好学的语言 学完Python让自己的工作效率提高几倍 不用每天熬夜加班 就能轻
  • LaTeX“U+200B”错误

    就是中文符号的问题 包括空格这种 我错的是空格问题 但空格我重新敲了一遍也不好使 翻到了另一个博主写的用Notepad 非常之好用 把那段报错文字复制过来 搜索 gt 替换 输入 u200b 找到中文空格位置 删除换成英文空格 再把这段文字
  • Android 性能优化 内存抖动 内存泄漏

    本文链接 https blog csdn net feather wch article details 131545501 云笔记链接 https note youdao com s YcbbhAYK 内存抖动 1 内存抖动是什么 内存可
  • C++图的建立---邻接矩阵-----邻接表

    目录 图的表示方式 邻接矩阵 邻接表 图的遍历 深度优先遍历 深度优先遍历算法步骤 图的广度优先遍历 广度优先遍历算法步骤 图的邻接矩阵存储来创建图 代码 运行结果 图的邻接表存储来创建图 如下图 运行结果 图的表示方式 图的表示方式有两种