图的存储(邻接矩阵邻接表)

news2025/1/21 15:30:09

图的存储

文章目录

  • 图的存储
    • 1 邻接矩阵
      • 1.1 邻接矩阵存储结构定义
      • 1.2 完整代码应用
    • 2 邻接表
      • 2.1 邻接表存储结构定义
      • 2.2 完整代码应用

1 邻接矩阵

  1. A [ i ] [ j ] = 1 A[i][j]=1 A[i][j]=1 表示顶点i与顶点j邻接,即ij之间存在边或者弧。

  2. A [ i ] [ j ] = 0 A[i][j]=0 A[i][j]=0 表示顶点i与顶点j不邻接。 (0≤i,j≤n-1)

图1 图的邻接矩阵存储
a)无权图 b)有权图



1.1 邻接矩阵存储结构定义

#define MaxVertexNum 100  //顶点数目的最大值
typedef char VertexType;	//顶点的数据类型
typedef int EdgeType;	//带权图中边上权值的数据类型
typedef struct{
    VertexType Vex[MaxVertexNum];	//顶点表,用来存储顶点
    EdgeType Edge[MaxVertexNum][MaxVertexNum];  //邻接矩阵,边表,用来存储边
    int vexnum, arcnum;	//图的当前顶点数和弧数
}MGraph;

注意邻接矩阵表示法的空间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n为图的顶点数 ∣ V ∣ |V| V



1.2 完整代码应用

以下图作为输入例子:

图2 无向图及其邻接矩阵



C++代码实现:
#include<iostream>//创建无向图的邻接矩阵
using namespace std;
#define MaxVnum 100  //顶点数最大值
typedef char VexType;  //顶点的数据类型,根据需要定义
typedef int EdgeType;  //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{
	VexType Vex[MaxVnum];
	EdgeType Edge[MaxVnum][MaxVnum];
	int vexnum,edgenum; //顶点数,边数
}AMGraph;

int locatevex(AMGraph G,VexType x){
	for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
		if(x==G.Vex[i])
			return i;
	return -1;//没找到
}


void CreateAMGraph(AMGraph &G){
	int i,j;
	VexType u,v;
	cout<<"请输入顶点数:"<<endl;
	cin>>G.vexnum;
	cout<<"请输入边数:"<<endl;
	cin>>G.edgenum;
	cout<<"请输入顶点信息:"<<endl;
	for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
		cin>>G.Vex[i];
	for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
		for(int j=0;j<G.vexnum;j++)
			G.Edge[i][j]=0;
	cout<<"请输入每条边依附的两个顶点:"<<endl;
	while(G.edgenum--){
		cin>>u>>v;
		i=locatevex(G,u);//查找顶点u的存储下标
		j=locatevex(G,v);//查找顶点v的存储下标
		if(i!=-1&&j!=-1)
			G.Edge[i][j]=G.Edge[j][i]=1; //邻接矩阵储置1,如果是有向图,则把'G.Edge[j][i]=1'去掉即可
		else{
			cout << "输入顶点信息错!请重新输入!"<<endl;
			G.edgenum++;//本次输入不算
		}
	}
}

void print(AMGraph G){//输出邻接矩阵
	cout<<"图的邻接矩阵为:"<<endl;
	for(int i=0;i<G.vexnum;i++){
		for(int j=0;j<G.vexnum;j++)
			cout<<G.Edge[i][j]<<"\t";
		cout<<endl;
	}
}

int main(){
	AMGraph G;
	CreateAMGraph(G);
	print(G);
	return 0;
}



输出结果

图3 样例输出结果



2 邻接表

图4 邻接表存储结构示例

图5 绿色部分相当于顶点表


图6 每一种颜色相当于一个边表


2.1 邻接表存储结构定义

#define MaxVertexNum 100  //顶点数目的最大值
typedef struct ArcNode{		//边表结点
	int adjvex;	 	//该弧所指向的顶点的位置
    struct ArcNode *next;	//指向下一条弧的指针
}ArcNode;
typedef struct VNode{	//顶点表结点
	VertexType data;	//顶点信息  
    ArcNode *first;  //指向第一条依附该顶点的弧的指针
}VNode, AdjList[MaxVertexNum];
typedef struct{
    AdjList vertices;	//邻接表
    int vexnum, arcnum;	//图的顶点数和弧数
}ALGraph;	//ALGraph是以邻接表存储的图类型



2.2 完整代码应用

以下图作为输入样例:

图7 邻接表输入样例

#include<iostream>//创建有向图的邻接表
using namespace std;
const int MaxVnum=100;//顶点数最大值
typedef char VexType;//顶点的数据类型为字符型

typedef struct AdjNode{ //定义邻接点类型
	int v; //邻接点下标
	struct AdjNode *next; //指向下一个邻接点
}AdjNode;

typedef struct VexNode{ //定义顶点类型
	VexType data; // VexType为顶点的数据类型,根据需要定义
	AdjNode *first; //指向第一个邻接点
}VexNode;

typedef struct{//定义邻接表类型
	VexNode Vex[MaxVnum];
	int vexnum,edgenum; //顶点数,边数
}ALGraph;

int locatevex(ALGraph G,VexType x){
	for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
		if(x==G.Vex[i].data)
			return i;
	return -1;//没找到
}

void insertedge(ALGraph &G,int i,int j){//插入一条边
	AdjNode *s;
	s=new AdjNode;
	s->v=j;
	s->next=G.Vex[i].first;
	G.Vex[i].first=s;
}

void printg(ALGraph G){//输出邻接表
	cout<<"----------邻接表如下:----------"<<endl;
	for(int i=0;i<G.vexnum;i++){
		AdjNode *t=G.Vex[i].first;
		cout<<G.Vex[i].data<<":  ";
		while(t!=NULL){
			cout<<"["<<t->v<<"]\t";
			t=t->next;
		}
		cout<<endl;
	}
}

void CreateALGraph(ALGraph &G){//创建有向图邻接表
	int i,j;
	VexType u,v;
	cout<<"请输入顶点数和边数:"<<endl;
	cin>>G.vexnum>>G.edgenum;
	cout<<"请输入顶点信息:"<<endl;
	for(i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
		cin>>G.Vex[i].data;
	for(i=0;i<G.vexnum;i++)
		G.Vex[i].first=NULL;
	cout<<"请依次输入每条边的两个顶点u,v"<<endl;
	while(G.edgenum--){
		cin>>u>>v;
		i=locatevex(G,u);//查找顶点u的存储下标
		j=locatevex(G,v);//查找顶点v的存储下标
		if(i!=-1&&j!=-1)
			insertedge(G,i,j);
		else{
			cout<<"输入顶点信息错!请重新输入!"<<endl;
			G.edgenum++;//本次输入不算
		}
	}
}

int main(){
	ALGraph G;
	CreateALGraph(G);//创建有向图邻接表
	printg(G);//输出邻接表
	return 0;
}




输出结果:

图8 样例输出结果(注:邻接表不唯一,因为插入结点顺序可以不同)

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

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

相关文章

使用jdk17 搭建Hadoop3.3.5和Spark3.3.2 on Yarn集群模式

搭建Hadoop3.3.5和Spark3.3.2 on Yarn集群模式&#xff0c;使用jdk17 搭建Hadoop3.3.5和Spark3.3.2 on Yarn集群模式1. 创建一台虚拟机2. 安装jdk17&#xff08;1&#xff09;下载jdk17&#xff08;2&#xff09;安装jdk17&#xff08;3&#xff09;配置环境变量 3. 虚拟机之间…

【音视频第15天】webRTC协议(2)

目录 协议ICESTUNNATTURNSDPSDP结构 Signaling and ConnectingSignaling: How peers find each other in WebRTCConnecting and NAT Traversal with STUN/TURN Signalingsdp协议WebRTC如何使用sdpWebRTC会话示例 Connecting为什么WebRTC需要一个专用的子系统来连接?现实世界的…

Day949.遗留系统之殇:为什么要对遗留系统进行现代化? -遗留系统现代化实战

遗留系统之殇&#xff1a;为什么要对遗留系统进行现代化&#xff1f; Hi&#xff0c;我是阿昌&#xff0c;今天学习记录是关于遗留系统之殇&#xff1a;为什么要对遗留系统进行现代化&#xff1f;的内容。 不知道你是否跟曾经一样&#xff0c;身处一个遗留系统的漩涡之中&…

数据结构-基数排序

基数排序是和其他的各类排序方式都不同的方式&#xff0c;之前的各类排序&#xff0c;如快速排序&#xff0c;堆排序&#xff0c;冒泡排序等等&#xff0c;都是通过关键字之间的比较和移动记录这两种操作来实现的&#xff0c;而基数排序不需要记录关键字之间的比较。所谓基数排…

ubuntu 安装vmware tool

1在虚拟机种站到安装vmware-tools 然后重启虚拟机 2在磁盘中可以看到如下文件&#xff0c;将zip文件移动到桌面解压备用 3关闭虚拟机 找到编辑虚拟机设置 4点击左侧 CD/dvd(SATA) 如果是使用镜像文件&#xff0c;改成使用物理驱动器. 5 打开命令行 cd 桌面 &#xff08;如…

CSS基础——盒子模型的一些属性概念

目录 display visibility overflow 文档流 元素在文档流中的特点 块元素 内联元素 浮动 float 浮动元素特点 清除浮动 clear 小练习 效果图 具体实现 高度塌陷问题 BFC 特点 如何开启BFC 解决方案 本篇的最终练习 效果图如下&#xff1a; 具体实现 disp…

ChatGPT原理解释

写了一本介绍ChatGPT原理的课程 结构如下 01、介绍ChatGPT及其原理 1.1 ChatGPT的概述 1.2 什么是自然语言处理&#xff08;NLP&#xff09; 1.3 深度学习与NLP的关系 1.4 GPT模型的介绍 02、GPT原理探讨 2.1 GPT模型的输入与输出 2.2 GPT模型的结构 2.3 GPT模型的预训练方法…

flv怎么无损转换成mp4格式,3大超级方法分享

flv格式是目前在视频分享媒体播放网站上广泛使用的一种视频文件格式&#xff0c;可以在网站窗口中直接播放&#xff0c;这类视频文件还能够有效保护版权。但是有些时候我们可能需要将flv格式的视频转换为其他格式&#xff0c;比如mp4。但是该怎么操作呢&#xff1f; 其实有很多…

数据挖掘:汽车车交易价格预测(测评指标;EDA)

目录 一、前期工作 1.赛题介绍 赛题分析&#xff1a; 分类和回归问题的评价指标有如下一些形式&#xff1a; &#xff08;下文2.1和2.2会用到&#xff09; 2.数据简介 3.探索性分析-EDA介绍 二、实战演练 2.1分类指标评价计算示例 2.2回归指标评价计算示例 2.3数据探索…

抠图,扣掉背景图片

Remove Image Backgrounds, Free HD, No Signup - Pixian.AI https://pixian.ai/ 从电脑本地选取图片&#xff0c;然后会自动扣掉背景&#xff0c;点击DOWNLOAD就可以了 第一个&#xff1a;Pixian.AI 这是一款国外的在线抠图网站&#xff0c;把需要扣除背景的图片拖拽进来&am…

简单的了解下 Fetch API 的工作原理

简介 Fetch API是一种现代的Web API&#xff0c;提供了一种异步获取网络资源的方法。由于其简单性、灵活性和一致性&#xff0c;它已经成为Web应用程序中获取数据和资源的流行选择。在本文中&#xff0c;我们将深入探讨Fetch API的核心特性&#xff0c;并了解其工作原理。 Fetc…

Windows逆向安全(一)之基础知识(七)

汇编C语言类型转换 类型转换 类型转换的使用场景 类型转换一般为由数据宽度小的转换成数据宽度大的&#xff0c;不然可能会有高位数据被截断的现象&#xff0c;引起数据丢失 需要一个变量来存储一个数据&#xff0c;刚开始这个数据的数据宽度较小&#xff0c;后来发现存不下…

什么是UML?

文章目录 00 | 基础知识01 | 静态建模类图对象图用例图 02 | 动态建模时序图通信图状态图活动图 03 | 物理建模构件图部署图 UML&#xff08;Unified Model Language&#xff09;&#xff0c;统一建模语言&#xff0c;是一种可以用来表现设计模式的直观的&#xff0c;有效的框图…

【图像分割】Grounded Segment Anything根据文字自动画框或分割环境配置和基本使用教程

1 环境配置 要求&#xff1a;python>3.8, pytorch>1.7, torchvision>0.8 官方地址&#xff1a;https://github.com/IDEA-Research/Grounded-Segment-AnythingMarrying Grounding DINO with Segment Anything & Stable Diffusion & BLIP & Whisper &am…

命运坎坷的保定县

保定的词语分解 保护而安定之。诗小雅天保&#xff1a;“天保定尔&#xff0c;亦孔之固。”谓稳固地保有。 晋 陆云 大将军宴会被命作诗&#xff1a;“皇皇帝祜&#xff0c;诞隆骏命。四祖正家&#xff0c;天禄保定。” 保定府&#xff1f;保定县&#xff1f; 今天提起“保定…

将“每日造型”变成长久习惯,戴森Airwrap™美发棒为何成为最好的“美丽投资”?

做头发、换发型是一个大工程&#xff0c;这几乎成了一种固定印象。虽然卷发棒已成为几乎“人手必备”的头发造型工具&#xff0c;但使用起来往往“现实很骨感”&#xff0c;不是使用频次极低&#xff0c;就是被束之高阁&#xff0c;每天都自己做头发换造型&#xff0c;只能是一…

陶泓达:4.19黄金原油早间精准策略!

黄金方面&#xff1a; 周二(4月18日)美市早盘&#xff0c;现货黄金一度跌至1991.05美元低点&#xff0c;但随后迅速拉升近20美元&#xff0c;向上触及2010.71美元高点&#xff0c;短线走出V型反转行情。本周&#xff0c;美国经济日历上没有太多关键数据会影响黄金和美元。因此&…

docker的数据卷详解

数据卷 数据卷是宿主机中的一个目录或文件&#xff0c;当容器目录和数据卷目录绑定后&#xff0c;对方修改会立即同步 一个数据卷可以同时被多个容器同时挂载&#xff0c;一个容器也可以被挂载多个数据卷 数据卷作用&#xff1a;容器数据持久化 /外部机器和容器间接通信 /容器…

leetCode算法第二天

好好刷刷算法题&#xff0c;提高自己的编码能力。 文章目录 将整数转为罗马数字将罗马数字转为整数编写一个函数来查找字符串数组中的最长公共前缀电话号码的字母组合 将整数转为罗马数字 leetcode链接&#xff1a;https://leetcode.cn/problems/integer-to-roman/ 解题思路…

施工阶段如何应用BIM技术,建模助手有话说

​近些年来&#xff0c;越来越多的建筑项目采用BIM来提升管理水平和品质&#xff0c;特别在施工阶段&#xff0c;通过BIM技术可以将施工现场3D模型与施工进度链接&#xff0c;超前模拟施工情况&#xff0c;完成各种精细化施工方案&#xff0c;除了保障施工工作顺利推进&#xf…