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++图的建立---邻接矩阵-----邻接表 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 配置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++图的建立---邻接矩阵-----邻接表

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