数据结构-----图(graph)的储存和创建

目录

前言

图的储存结构

1.邻接矩阵

无向图的邻接矩阵

 有向图的邻接矩阵

网(赋权图)的邻接矩阵

 代码表示

2.邻接表

无向图的邻接表

有向图的邻接表

代码表示

3.邻接矩阵和邻接表对比

邻接矩阵

邻接表

图的创建

1.邻接矩阵创建图(网)

 2.邻接表创建图(网)


前言

        上一期我们学习了图的基础知识(链接:数据结构-----图(Graph)论必知必会知识-CSDN博客),这一期我们就学习怎么去储存图,和创建一个图,下面就一起来看看。

图的储存结构

1.邻接矩阵

邻接矩阵是图的矩阵表示,借助它可以方便地存储图的结构,用线性代数的方法研究图的问题。 如果一个图有 n 个顶点,其邻接矩阵 W 为 ntimes n 的矩阵,矩阵元素 w_ {ij} 表示边 (i,j) 的权重。 如果两个顶点之间没有边连接,则在邻接矩阵中对应的元素为0。

一个图G有n个顶点,就需要nxn矩阵来去表示。 

无向图的邻接矩阵

无向图的邻接矩阵特点:

  • 主对角线为0,右上和左下部分对称 
  • 第i个顶点的度等于第i行1的个数和,等于第i列1的个数和
 有向图的邻接矩阵

有向图的邻接矩阵特点:

  • 主对角线为0,不一定对称
  • 第i个顶点的出度等于第i行1的个数
  • 第i个顶点的入度等于第i列1的个数
  • 顶点的度=第i行元素之和+第i列元素之和
网(赋权图)的邻接矩阵

网是带有路径长度的图,所以对比上面的矩阵,我们只需要把通路1,换成路径的长度即可。

 代码表示
#define Maxnum 100//最大顶点数
//数据类型
typedef struct d { char id[10];//……
}
ElemType;
//图的邻接数组
typedef struct graph {ElemType vexs[Maxnum];//图数据int arcs[Maxnum][Maxnum];//二维数组int vexnum;//点数int arcnum;//边数
}Graph;

2.邻接表

邻接表是图的一种最主要存储结构,用来描述图上的每一个点。对于图的每个顶点建立一个容器( n个顶点建立 n 个容器),第 i 个容器中的结点包含顶点vi 的所有邻接顶点。

一个邻接表需要两种存储结构:顶点表结点边表结点 

  • 顶点:
    •  按编号顺序将顶点数据存储在一维数组中
  • 关联同一顶点的边 (以顶点为尾的弧)
    • 用线性链表存储

无向图的邻接表

特点:

  • 邻接表不唯一
  • 若无向图中有 n个顶点e条边,则其邻接表需 n个头结点和2e 个表结点。适宜存储稀疏图。

有向图的邻接表

特点:

  • 找出度易找入度难
  • 顶点 vi的出度为第i个单链表中的结点个数。
  • >顶点 vi的入度为整个单链表中邻接点域值是 i-1的结点个数。

代码表示
//数据结构体
typedef struct d {char id[10];//字符串编号//………………
}ElemType;
//边节点存储结构
typedef struct arcnode {int index;//指向顶点的位置int weight;//权struct arcnode* nextarc;//指向下一个边节点
}Anode;
//顶点结点存储结构
typedef struct vexnode {ElemType data;Anode* firstarc;
}Vhead;
//图结构
typedef struct {Vhead* vertices;int vexnum;int arcnum;
}Graph;

3.邻接矩阵和邻接表对比

邻接矩阵

 优点

  • 直观、简单、好理解
  • 方面检查任意一对顶点间是否存在边
  • 方便找任一顶点的所有“邻接点”(有边直接相连的顶点)
  • 方便计算任一顶点的“度”

缺点

  • 不便于增加和删除顶点
  • 浪费空间——存稀疏图 (点很多而边很少)有大量无效元素,但是对密图 (特别是完全图) 还是很合算的
  • 浪费时间——统计稀疏图中一共有多少条边
邻接表

优点

  • 对于稀疏图来说,邻接表比邻接矩阵更加省空间。
  • 方便遍历某个顶点的所有邻接点,时间复杂度为 O (degree)。
  • 邻接表算法实现简单,易于修改和扩展。

 缺点

  • 重边不好处理 判重比较麻烦 ,还要遍历已有的边,不能直接判断
  • 对确定边的操作效率不高
  • 不方便计算顶点的入度

图的创建

1.邻接矩阵创建图(网)

下面代码是无向网的创建 

#include<stdio.h>
#include<stdlib.h>#define Maxint 32767
#define Maxnum 100//最大顶点数
//数据类型
typedef struct d { char id[10];//……
}
ElemType;
//图的邻接数组
typedef struct graph {ElemType vexs[Maxnum];//图数据int arcs[Maxnum][Maxnum];//二维数组int vexnum;//点数int arcnum;//边数
}Graph;//节点id查找下标
int Locate_vex(Graph G, char* id) {for (int i = 0; i < G.vexnum; i++)if (strcmp(G.vexs[i].id,id)==0)return i;return -1;
}//构造邻接矩阵(无向图,对称矩阵)(有向图)赋权图
void Create_graph(Graph* G) {printf("请输入顶点个数和边的个数:\n");scanf("%d %d", &G->vexnum, &G->arcnum);//输入点数边数printf("请输入顶点数据:\n");for (int i = 0; i < G->vexnum; i++) {scanf("%s", G->vexs[i].id);}for (int x = 0; x < G->vexnum; x++) {for (int y = 0; y < G->vexnum; y++) {if (x == y)G->arcs[x][y] = 0;//对角线初始化为0elseG->arcs[x][y] = Maxint;//其他初始化为Maxint}}printf("请输入边相关数据:\n");for (int k = 0; k < G->arcnum; k++) {char a[10], b[10];int w;scanf("%s %s %d", a, b, &w);//a->bint i = Locate_vex(*G, a);int j = Locate_vex(*G, b);//矩阵赋值G->arcs[i][j] = w;G->arcs[j][i] = w;//删掉这个,表示有向图}
}//输出矩阵
void print_matrix(Graph G) {printf("矩阵为:\n");for (int i = 0; i < G.arcnum; i++) {for (int j = 0; j < G.arcnum; j++)printf("%-5d ", G.arcs[i][j]);printf("\n");}printf("图的顶点个数和边数:%d,%d\n", G.vexnum, G.arcnum);
}

结果如下: 

输入图的结构如下所示: 

 2.邻接表创建图(网)

对于邻接表的创建,我们是先去创建好顶点表数组,然后通过遍历和头插法把数据作为边表节点插入到顶点表的后面,最后形成邻接表链。代码如下:

#include<stdio.h>
#include<string.h>
//数据结构体
typedef struct datatype {char id[10];//字符串编号//………………
}ElemType;
//边节点存储结构
typedef struct arcnode {int index;//指向顶点的位置int weight;//权struct arcnode* nextarc;//指向下一个边节点
}Anode;
//顶点结点存储结构
typedef struct vexnode {ElemType data;Anode* firstarc;
}Vhead;
//图结构
typedef struct {Vhead* vertices;int vexnum;int arcnum;
}Graph;//顶点查找下标
int Locate_vex(Graph G, ElemType v) {for (int i = 0; i < G.vexnum; i++)if (strcmp(G.vertices[i].data.id,v.id)==0)return i;return -1;
}//创建头节点
void Create_vexhead(Graph *G,int n) {G->vertices = (Vhead*)malloc(sizeof(Vhead) *n);if (!G->vertices) {printf("ERROR\n");exit(-1);}else {for (int i = 0; i < n ; i++) {scanf("%s", G->vertices[i].data.id);G->vertices[i].firstarc = NULL;}}
}
//创建一个边节点
Anode* Create_arcnode(int loca, int w) {Anode* arc = (Anode*)malloc(sizeof(Anode));if (!arc){printf("ERROR\n");exit(-1);}arc->index = loca;arc->nextarc = NULL;arc->weight = w;return arc;
}
//创建邻接表(无向图)(有向图)
void Create_graph(Graph* G) {printf("输入顶点数和边数:\n");scanf("%d %d", &G->vexnum, &G->arcnum);printf("输入顶点数据:\n");Create_vexhead(G, G->vexnum);printf("输入边数据:\n");for (int k = 0; k <G->arcnum; k++) {ElemType a, b;int w;scanf("%s%s%d", a.id, b.id, &w);int i = Locate_vex(*G, a);int j = Locate_vex(*G, b);//头插法//a->bAnode* p = Create_arcnode(j, w);p->nextarc = G->vertices[i].firstarc;G->vertices[i].firstarc = p;//如果创建有向图的话,直接把下面的代码删掉即可//b->aAnode* q = Create_arcnode(i, w);q->nextarc = G->vertices[j].firstarc;G->vertices[j].firstarc = q;}
}//访问
void visit(Graph G, int index) {printf("%s ", G.vertices[index].data.id);
}//输出图
void print(Graph G) {printf("以下是图的顶点连接关系:\n");for (int i = 0; i < G.vexnum; i++) {printf("%s:", G.vertices[i].data.id);Anode* cur= G.vertices[i].firstarc;while (cur) {visit(G, cur->index);cur = cur->nextarc;}printf("\n");}printf("顶点和边数分别是:%d %d\n", G.vexnum, G.arcnum);
}

测试结果:

好了,以上就是今天的全部内容了,我们下一期学习图的遍历,下次见咯! 

分享一张壁纸:

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

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

相关文章

原子核内的相互作用

原子核内的相互作用 氘核基态 和态的混合 核子-核子散射 低能核子-核子散射 n-p散射&#xff1a;只有核力 p-p散射&#xff1a;较复杂 n-n散射&#xff1a;n-n散射没有直接实验 低能 p-p 散射和核力的电荷无关性 高能核子-核子散射 核力的主要性质 核力主要性质 核力是短程力…

国旗升降系统程序及原理图资料

本文主要介绍国旗升降系统设计程序及原理图&#xff08;完整资料见文末链接&#xff09; 系统原理图如下&#xff0c;程序资料见文末 附完整资料链接 百度网盘链接: https://pan.baidu.com/s/1Q5J2J8LgVJ-hoeTSVP95_g?pwd3qkw 提取码: 3qkw

js鼠标点击添加图标并获取图标的坐标值

给这个图片添加摄像头图标&#xff0c;并获取图标的坐标值&#xff0c;也就是图标的css样式是positon:absolute,获取left和top的值。 图片1 思路是这样的&#xff0c;获取这里的长度&#xff0c; 图片2 1.鼠标点击时距浏览器的左边距离和上边距离&#xff0c;相当于(0,0)坐标 …

零基础搭建个人网站详细流程

最近两天&#xff0c;为了给自己的工具类APP备案&#xff0c;买了阿里云ECS和域名。虽然很想说离线工具APP不用联网&#xff0c;但是现实就很无语。言归正传&#xff0c;既然买了总不能将它们闲置着&#xff0c;就诞生了建站的想法&#xff0c;至少还能放个用户协议和隐私协议。…

『ARM』和『x86』处理器架构解析指南

前言 如果问大家是否知道 CPU&#xff0c;我相信不会得到否定的答案&#xff0c;但是如果继续问大家是否了解 ARM 和 X86 架构&#xff0c;他们的区别又是什么&#xff0c;相信可能部分人就会哑口无言了 目前随着深度学习、高性能计算、NLP、AIGC、GLM、AGI 的技术迭代&#…

【c语言】atoi的模拟实现

1.头文件 atoi() 是 C语言的一个标准库函数&#xff0c;定义在<stdlib.h>头文件中 2.atoi的解析 具体来讲&#xff0c;atoi() 函数首先会丢弃尽可能多的空白字符&#xff0c;直至找到第一个非空白字符&#xff0c;然后从该字符开始&#xff0c;识别 “”、“-” 以及 …

【脉冲通信】用于空间应用的飞秒脉冲通信的符号误码率模型研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

TCP通信实战:模拟BS系统

1、之前的客户端都是什么样的 其实就是CS架构&#xff0c;客户端是需要我们自己开发实现的 2、BS结构是什么样的&#xff0c;需要开发客户端吗&#xff1f; 浏览器访问服务端&#xff0c;不需要开发客户端 注意&#xff1a;服务端必须给浏览器响应HTTP协议格式的数据&#xff0…

[swift刷题模板] 树状数组(BIT/FenwickTree)

[TOC]([swift刷题模板] 树状数组(BIT/FenwickTree) ) 一、 算法&数据结构 1. 描述 [python刷题模板] 树状数组 二、 模板代码 1. 单点赋值(增加)&#xff0c;区间求和(PURQ) 例题: 307. 区域和检索 - 数组可修改 class BIT {var c: [Int]var n: Int init(_ n: Int){c…

基于SpringBoot的招生管理系统

基于SpringBoot的招生管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登录界面 管理员界面 用户界面 摘要 基于SpringBoot的招生管理系统是一款现…

node快速搭建一个学习资料共享平台

概述 本文要实现的功能比较简单&#xff1a;1、将想要共享的文件分文件夹的组织起来&#xff1b;2、别人可以通过界面进行搜索&#xff1b;3、可以在线预览或下载文件。基于这样的需求&#xff0c;本文分享通过node如何实现这样的功能。 实现效果 实现 1. node端服务 node端…

基于SSM的大学校医管理系统

基于SSM的大学校医管理系统、学校医院管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登录系统 用户界面 管理员界面 摘要 大学校医管理系统…

​蔚来自动驾驶,从 2020 年开始讲起的故事

2020 年底&#xff0c;摆脱 2019 年阴霾的李斌先生&#xff0c;热情而兴奋&#xff0c;再一次说&#xff1a;「欢迎来到蔚来日。」 那天蔚来发布了令人咋舌的智能驾驶硬件系统&#xff0c;4 块当时甚至还没有宣布量产日期的 Orin 芯片&#xff0c;11 路高清摄像头。 早在 ET7…

汽车智能制造中的RFID技术在供应链生产管理中的应用

行业背景 汽车零部件工业是汽车工业中至关重要的一部分&#xff0c;对于汽车工业的长期稳定发展起着基础性的作用&#xff0c;近年来&#xff0c;汽车配件配套市场规模达到了2000亿元&#xff0c;维修市场达到了600亿元&#xff0c;随着汽车国产化的推进&#xff0c;汽车零部件…

【TensorFlow1.X】系列学习笔记【入门二】

【TensorFlow1.X】系列学习笔记【入门二】 大量经典论文的算法均采用 TF 1.x 实现, 为了阅读方便, 同时加深对实现细节的理解, 需要 TF 1.x 的知识 文章目录 【TensorFlow1.X】系列学习笔记【入门二】前言神经网络的参数神经网络的搭建前向传播反向传播 总结 前言 学习了张量、…

Pandas数据处理分析系列3-数据如何预览

Pandas-数据预览 Pandas 导入数据后,我们通常需要对数据进行预览,以便更好的进行数据分析。常见数据预览的方法如下: ①head() 方法 功能:读取数据的前几行,默认显示前5行 语法结构:df.head(行数) df1=pd.read_excel("销售表.xlsx",sheet_name="手机销…

WMS透明仓库:实现仓储的全方位可视化与优化

一、WMS透明仓库的定义与特点 1. WMS透明仓库的定义&#xff1a;WMS透明仓库是一种基于信息技术的仓库管理系统&#xff0c;通过实时数据采集、分析和可视化&#xff0c;将仓库内外的物流流程、库存状态、人员活动等信息以透明的方式展示给相关利益方。 2. 实时数据采集&…

Hadoop学习总结(搭建Hadoop集群(完全分布式模式))

学习搭建Hadoop集群&#xff08;完全分布式模式&#xff09; 链接&#xff1a;https://pan.baidu.com/s/1wwTKk-XxHbccHjE-Xk2PTA 提取码&#xff1a;q7j7 在SecurityCRT 或者在 Xshell 进行虚拟机链接 &#xff08;这里使用Xshell &#xff09; 在hadoop001里配置 如果没…

中文编程开发语言工具构件说明:屏幕截取构件的编程操作

屏幕截取 用于截取指定区域的图像。 图 标&#xff1a; 构件类型&#xff1a;不可视 重要属性 l 截取类型 枚举型&#xff0c;设置在截取屏幕时的截取类型。包括&#xff1a;全屏幕、指定区域、活动窗口三种。当全屏幕截取时相当于执行了硬拷屏&#xff08;PrintScre…

0基础学习PyFlink——模拟Hadoop流程

学习大数据还是绕不开始祖级别的技术hadoop。我们不用了解其太多&#xff0c;只要理解其大体流程&#xff0c;然后用python代码模拟主要流程来熟悉其思想。 还是以单词统计为例&#xff0c;如果使用hadoop流程实现&#xff0c;则如下图。 为什么要搞这么复杂呢&#xff1f; 顾…