图的顺序存储(邻接矩阵存储)【摘录自严长生老师的网站】

图是表达多对多关系的一种数据结构,组成要素为顶点和连接顶点的边。

根据边有无方向可分为有向图和无向图

当边有权重时,升级为有向网和无向网

图在存储时,可采用邻接矩阵,比如下面的无向图(A)和(B)

用邻接矩阵可分别表示为下面这样

每一行代表一个顶点,每一列也对应一个顶点,对于无向图,边没有方向,顶点之间相互连接,则对应位置设为1,否则为0,无向图的邻接矩阵是对称的。

对于有向图,边是有方向的,所以有向图的边不叫边,叫有向边或者弧,个人觉得有向边更直观,那么有向图的行,代表着该顶点到达哪些顶点,可达的记为1,否则为0,有向图的列,代表着该顶点可由哪些顶点到达,可达的记为1,否则为0。

有了这些基本概念,就可以基于C语言实现其存储了,注意,这里采用的是邻接矩阵的存储方式。

上代码。

#include <stdio.h>
#define MAX_VERtEX_NUM 20                   //顶点的最大个数
#define VRType int                          //表示顶点之间的关系的变量类型
#define InfoType char                       //存储弧或者边额外信息的指针变量类型
#define VertexType int                      //图中顶点的数据类型
typedef enum{DG,DN,UDG,UDN}GraphKind;       //枚举图的 4 种类型
typedef struct {VRType adj;                             //对于无权图,用 1 或 0 表示是否相邻;对于带权图,直接为权值。InfoType * info;                        //弧或边额外含有的信息指针
}ArcCell,AdjMatrix[MAX_VERtEX_NUM][MAX_VERtEX_NUM];
typedef struct {VertexType vexs[MAX_VERtEX_NUM];        //存储图中顶点数据AdjMatrix arcs;                         //二维数组,记录顶点之间的关系int vexnum,arcnum;                      //记录图的顶点数和弧(边)数GraphKind kind;                         //记录图的种类
}MGraph;
//根据顶点本身数据,判断出顶点在二维数组中的位置
int LocateVex(MGraph * G,VertexType v){int i=0;//遍历一维数组,找到变量vfor (; i<G->vexnum; i++) {if (G->vexs[i]==v) {break;}}//如果找不到,输出提示语句,返回-1if (i>G->vexnum) {printf("no such vertex.\n");return -1;}return i;
}
//构造有向图
void CreateDG(MGraph *G){//输入图含有的顶点数和弧的个数scanf("%d,%d",&(G->vexnum),&(G->arcnum));//依次输入顶点本身的数据for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}//初始化二维矩阵,全部归0,指针指向NULLfor (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}//在二维数组中添加弧的数据for (int i=0; i<G->arcnum; i++) {int v1,v2;//输入弧头和弧尾scanf("%d,%d",&v1,&v2);//确定顶点位置int n=LocateVex(G, v1);int m=LocateVex(G, v2);//排除错误数据if (m==-1 ||n==-1) {printf("no this vertex\n");return;}//将正确的弧的数据加入二维数组G->arcs[n][m].adj=1;}
}
//构造无向图
void CreateDN(MGraph *G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2;scanf("%d,%d",&v1,&v2);int n=LocateVex(G, v1);int m=LocateVex(G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=1;G->arcs[m][n].adj=1;//无向图的二阶矩阵沿主对角线对称}
}
//构造有向网,和有向图不同的是二阶矩阵中存储的是权值。
void CreateUDG(MGraph *G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2,w;scanf("%d,%d,%d",&v1,&v2,&w);int n=LocateVex(G, v1);int m=LocateVex(G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=w;}
}
//构造无向网。和无向图唯一的区别就是二阶矩阵中存储的是权值
void CreateUDN(MGraph* G){scanf("%d,%d",&(G->vexnum),&(G->arcnum));for (int i=0; i<G->vexnum; i++) {scanf("%d",&(G->vexs[i]));}for (int i=0; i<G->vexnum; i++) {for (int j=0; j<G->vexnum; j++) {G->arcs[i][j].adj=0;G->arcs[i][j].info=NULL;}}for (int i=0; i<G->arcnum; i++) {int v1,v2,w;scanf("%d,%d,%d",&v1,&v2,&w);int m=LocateVex(G, v1);int n=LocateVex(G, v2);if (m==-1 ||n==-1) {printf("no this vertex\n");return;}G->arcs[n][m].adj=w;G->arcs[m][n].adj=w;//矩阵对称}
}
void CreateGraph(MGraph *G){//选择图的类型scanf("%d",&(G->kind));//根据所选类型,调用不同的函数实现构造图的功能switch (G->kind) {case DG:return CreateDG(G);break;case DN:return CreateDN(G);break;case UDG:return CreateUDG(G);break;case UDN:return CreateUDN(G);break;default:break;}
}
//输出函数
void PrintGrapth(MGraph G)
{for (int i = 0; i < G.vexnum; i++){for (int j = 0; j < G.vexnum; j++){printf("%d ", G.arcs[i][j].adj);}printf("\n");}
}
int main() {MGraph G;//建立一个图的变量CreateGraph(&G);//调用创建函数,传入地址参数PrintGrapth(G);//输出图的二阶矩阵return 0;
}

  以下面这张图为例

对应的输入输出为

2
6,10
1
2
3
4
5
6
1,2,5
2,3,4
3,1,8
1,4,7
4,3,5
3,6,9
6,1,3
4,6,6
6,5,1
5,4,5
0 5 0 7 0 0
0 0 4 0 0 0
8 0 0 0 0 9
0 0 5 0 0 6
0 0 0 5 0 0
3 0 0 0 1 0

这是按照邻接矩阵来存储的,邻接矩阵的空间开销是固定的,因此当矩阵比较稠密时比较划算,当顶点之间的连接比较稀疏时,采用邻接表更合适。

 

转载于:https://www.cnblogs.com/wzyuan/p/10007789.html

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

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

相关文章

Neo4j:使隐式关系成为显式和双向关系

最近&#xff0c;我阅读了Michal Bachman关于 Neo4j中双向关系的文章 &#xff0c;他建议对于某些关系类型&#xff0c;我们对关系的方向不那么感兴趣&#xff0c;因此可以在查询时忽略它。 他使用以下示例显示了Neo Technology和GraphAware之间的合作关系&#xff1a; 两家公…

复旦大学计算机学院博士生王斌,复旦大学计算机科学技术学院博士生刘鹏飞荣获...

计算机科学技术学院发布时间:2017-01-04 小字体 中字体 大字体2016年12月22日,历时七个月选拔的2016年度百度奖学金获奖者揭晓,复旦大学计算机科学技术学院2014级博士生刘鹏飞以其在“自然语言处理与深度学习”上取得的突出成绩,从国内外近百所著名高校数百位竞争者中脱颖而出,…

Deno 兼容浏览器具体指的是什么?

Deno 里面有一句描述&#xff1a;"Aims to be browser compatible"&#xff0c;可以看到 Deno 的目标是兼容浏览器。那么这里的兼容浏览器到底如何是什么意思呢&#xff1f; 我简单谈谈我的理解吧。 首先这里的兼容性肯定不是 Deno 直接在浏览器端运行。因为 Deno …

判断按键值_「正点原子NANO STM32开发板资料连载」第十六章电容触摸按键实验...

1&#xff09;实验平台&#xff1a;ALIENTEK NANO STM32F411 V1开发板2&#xff09;摘自《正点原子STM32F4 开发指南&#xff08;HAL 库版》关注官方微信号公众号&#xff0c;获取更多资料&#xff1a;正点原子第十六章电容触摸按键实验上一章&#xff0c;我们介绍了 STM32F4 的…

将社交登录添加到Spring MVC Web应用程序:注册和登录

本教程的第一部分描述了如何配置Spring Social 1.1.0和Spring Security 3.2.0&#xff0c;但它留下了两个非常重要的问题尚未解答。 这些问题是&#xff1a; 用户如何创建新用户帐户&#xff1f; 用户如何登录&#xff1f; 现在该弄脏我们的手并回答这些问题了。 我们的示例…

实验五 编写、调试具有多个段的程序

&#xff08;1&#xff09;将下面的程序编译、连接&#xff0c;用Debug加载、跟踪&#xff0c;然后回答问题。 ①CPU执行程序&#xff0c;程序返回前&#xff0c;data段的数据为多少&#xff1f; 见下图d 0770:0000 000f结果。 ②CPU执行程序&#xff0c;程序返回前&#xff0c…

手机工商银行怎么转账_工商银行信用卡要哪些申请条件?想成功办理你需要了解这些!...

工商银行信用卡一直是卡友们热议的对象&#xff0c;也有不少卡友问过小白&#xff1a;工商银行信用卡怎么办理&#xff1f;要哪些条件&#xff1f;要等多长时间&#xff1f;那么今天小白就为大家详细的讲解一下工商银行信用卡申请的各种方法和技巧&#xff0c;希望对大家有帮助…

数据可视化的基本原理——视觉通道

数据可视化为了达到增强人脑认知的目的&#xff0c;会利用不同的视觉通道对冰冷的数据进行视觉编码。 我们在数据可视化的时候&#xff0c;一方面&#xff0c;展现可视化对象本身的位置、特性&#xff0c;对应的视觉通道类型是定性或者分类&#xff0c;比如汽车在什么地方、汽…

linux测试地址是否能访问_一个小测试能看出孩子注意力是否集中,提前弥补,上小学会很轻松...

文|秘籍君不少家长虽然重视孩子的教育&#xff0c;却总是习惯“临阵磨枪”&#xff0c;具体体现在&#xff1a;孩子在上幼儿园的前一两个月才开始着急&#xff0c;害怕孩子适应不了幼儿园&#xff1b;孩子上了大班才开始重视“幼小衔接”&#xff0c;却不知道&#xff0c;从孩子…

服务器怎么禁止iis静态文件,如何禁止IIS缓存静态文件

禁止IIS缓存静态文件(png、js、html等)背景&#xff1a;IIS为了提高性能&#xff0c;默认情况下会对静态文件js、html、gif、png等做内部缓存&#xff0c;这个缓存是在服务器iis进程的内存中的。IIS这么做在很大程度上可以提高静态文件的访问性能&#xff0c;在正常情况下只要静…

汇编实验五

一、 二、 三、 四、 第一个 反汇编后发现不行 第二个 发现也不行 第三个 发现代码正确 五、 编写代码如下 调试后查看内存&#xff0c;发现数据相加了 六、 编写代码如下 发现逆序存储成功 七、实验总结 对于代码段的使用有了更加深入的了解。 但是对于代码段内存这块还是不懂…

eclipse RTC下载的代码无android sdk

问题现象&#xff1a; 修复过程&#xff1a; 1.无ADT&#xff0c;安装ADT&#xff08;FQ操作&#xff09; https://dl-ssl.google.com/android/eclipse/ a图 b图 2.下载android sdk a.下载 3.应用到eclipse中去 转载于:https://www.cnblogs.com/liuyj-vv/p/9299913.html

亚马逊免费使用套餐:在EC2 Linux实例上安装Tomcat 7

Amazon Web Services提供了12个月的免费使用期限&#xff0c;使开发人员可以在云中运行任何他们想要的东西。 免费层包括14个服务&#xff0c;其中Web开发人员最关注EC2服务。 EC2是一项服务&#xff0c;通过停止和启动Windows和/或Linux的虚拟实例来提供可调整大小的虚拟计算。…

笔记:隐式转换规则

学习并背诵全文 原始值 类型UndefinedNullStringBooleanNumber值undefinednull所有字符串true false所有数字/NaN 引用类型 Object的成员叫对象&#xff0c;包括Array&#xff0c;Function&#xff0c;Math&#xff0c;Date&#xff0c;JSON&#xff0c;RegExp等除了原始值…

ble连接过程建立_九点之蓝牙连接

蓝牙连接蓝牙连接是如何进入到连接状态呢&#xff0c;首先必须经历前面提到的广播阶段&#xff0c;主端通过扫描到从端的广播来发现这个设备&#xff0c;之后让主端发出连接请求来要求与从端建立连接&#xff0c;便可以进入到连接状态。由于蓝牙连接牵涉的点比较多&#xff0c;…

华为服务器系统蓝屏,服务器主机蓝屏

服务器主机蓝屏 内容精选换一换云服务器创建后区域固定&#xff0c;不能将云服务器转移到另一个区域&#xff0c;也不能将云服务器转移到另一个帐号。您可以通过镜像迁移方式实现云服务器的跨帐号跨区域迁移。服务器迁移的常见场景与常用的迁移方式请参考常见的服务器迁移场景。…

多对一映射、一对多映射

Emp员工表 Dept部门表 多对一映射 在查询时&#xff0c;需要获取两张以上关联表的数据&#xff0c;通过关联映射&#xff0c;可以由一个对象获取关联对象的信息&#xff0c;例如&#xff1a;查询一个Emp员工对象&#xff0c;可以 通过关联映射获取员工所在的部门Dept对象信息 …

一道面试题目引发的思考

起因 多列布局是前端一个经典的反复被提及的面试题目&#xff0c;最典型的即两列&#xff0c;左列定宽菜单栏&#xff0c;右列变宽为内容区域。 通常得到的答案无外乎左列浮动定宽&#xff0c;然后右列或浮动&#xff0c;或设置外边距&#xff0c;或绝对定位等等。偶尔会有面试…

uniapp弹出框_uniApp上拉刷新,下拉加载,以及筛选功能

uniApp插件市场有很多友好的插件&#xff0c;今天举一个例子如上图所示&#xff0c;实现上拉刷新&#xff0c;下来加载&#xff0c;右上角点击弹出筛选框&#xff0c;只需要在插件市场搜索刷新选择你想要的效果(也可以下载后自己改动效果)点击导入插件&#xff0c;会自动打开项…

乐高无限的服务器怎么建,乐高无限悬空房子怎么建造 建造方法介绍

乐高无限悬空房子怎么建造?很多玩家对此还不是很清楚&#xff0c;下面给大家带来乐高无限悬空房子建造方法&#xff0c;还不知道怎么建造的朋友一起来看看吧!建造方法悬空房子非常容易搭建&#xff0c;如果我们想要将已经搭建的房子悬空&#xff0c;就只需要将建筑下方的土地挖…