DSA之图(2):图的存储结构

news2024/11/16 11:24:45

文章目录

  • 0 图的结构
  • 1 邻接矩阵
    • 1.1 无向图的邻接矩阵
    • 1.2 有向图的邻接矩阵
    • 1.3 网(有权图)的邻接矩阵表示法
    • 1.4 邻接矩阵的建立
      • 1.4.1 采用邻接矩阵建立无向网
      • 1.4.2 采用邻接矩阵建立有向网
    • 1.5 邻接矩阵的优缺点
      • 1.5.1 优点
      • 1.5.2 缺点
  • 2 邻接表
    • 2.1 无向图的邻接表
    • 2.2 有向图的邻接表
    • 2.3 邻接表的建立
      • 2.3.1 采用邻接表建立无向网
      • 2.3.2 采用邻接表建立有向网
    • 2.4 邻接表的特点
  • 3 邻接矩阵与邻接表的区别
    • 3.1 联系
    • 3.2 区别
  • 4 改进的邻接表
    • 4.1 十字链表---用于有向图
    • 4.2 邻接多重表
  • 5 总结

0 图的结构

多对多的结构,不能跟以前一样确定多少个数据域和指针域来进行表示。主要介绍邻接矩阵和邻接表。


在这里插入图片描述

1 邻接矩阵

在这里插入图片描述
尖括号表示有序的,有向图;圆括号表示无序的,无向图。有边的记作1,没有边的记为0。

1.1 无向图的邻接矩阵

在这里插入图片描述
特点:

  1. 对角线都是0,因为自身对自身没有边
  2. 无向图的邻接矩阵是对称的,两个顶点的边是相互的;但是并不能说有向图的邻接矩阵一定是不对称
  3. 度是与顶点相关联的边的个数,反映到图上来说,就是找1的个数,即:顶点 i i i的度 = 第 i i i行(列)中1的个数,即行(列)元素之和
  4. 完全图的邻接矩阵,对角线的元素为0,其余为1

1.2 有向图的邻接矩阵

有向图的邻接矩阵不一定是对称的,因为两个相连的顶点可能不是双向的。
在这里插入图片描述

  1. i i i行,表示从 v i v_i vi个节点发出的弧,称之为出度。
  2. i i i列,表示从 v i v_i vi个节点接收的弧,称之为入度。
  3. 顶点的出度=第 i i i行元素之和
  4. 顶点的入度=第 i i i列元素之和
  5. 顶点的度=第 i i i行元素之和+第 i i i列元素之和

1.3 网(有权图)的邻接矩阵表示法

在这里插入图片描述
相当于就是把权值代替成了普通的边。
在这里插入图片描述
以上就是网的邻接矩阵。

1.4 邻接矩阵的建立

#define MaxInt 32767 //表示无穷大
#define MVNum 100
typedef char VerTexType;//设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型

typedef struct
{
    VerTextType vex[MVNum];//顶点表
    ArcType arcs[MVNum][MVNum];//邻接矩阵
    int vexnum, arcnum; //图的当前点数和边数
}AMGraph;

1.4.1 采用邻接矩阵建立无向网

在这里插入图片描述

#define MaxInt 32767 //表示无穷大
#define MVNum 100
typedef char VerTexType;//设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型

typedef struct
{
    VerTextType vex[MVNum];//顶点表
    ArcType arcs[MVNum][MVNum];//邻接矩阵
    int vexnum, arcnum; //图的当前点数和边数
}AMGraph;//邻接矩阵表示的图

int LocateVex(AMGraph G, VertexType u)//查找顶点所在的位置
{
    int i;
    for (i = 0; i < G.vexnum; ++i)
    {
        if (u == G.vex[i])
        {
            return i;//找到元素在图当中的下标
        } 
    }
    return -1;
}

//构建无向网
Status CreateUDN(AMGraph &G)//G有四个成员,顶点表,边表,点数和边数
{
    cin >> G.vexnum >> G.arcnum;//输入总顶点数,总边数
    for (i = 0; i < G.vexnum; ++i)
    {
        cin >> G.vex[i];//依次输入点的信息
    }
    for (i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
    {
        for (j = 0; i < G.vexnum; ++j)
        {
            G.arcs[i][j] = MaxInt;//边的权值均初始化为最大值
        }
    }
    for (k = 0; k < G.arcnum; ++k)//构造邻接矩阵
    {
        cin >> v1 >> v2 >> w;//输入一条边所依附的顶点以及边的权值
        i = LocateVex(G, v1);//确定v1和v2在G中的位置
        j = LocateVex(G, v2);
        G.arcs[i][j] = w;//边<v1,v2>的权值置为w
        G.arcs[j][i] = G.arcs[i][j];
    }//for
    return OK;
}//CreateUDN

1.4.2 采用邻接矩阵建立有向网

在这里插入图片描述
无需向邻接矩阵双向赋值,只需要赋值单边的就行。

1.5 邻接矩阵的优缺点

1.5.1 优点

在这里插入图片描述

1.5.2 缺点

在这里插入图片描述
时间复杂度只与顶点有关,与边数无关,时间复杂度为 O ( n 2 ) O(n^2) O(n2)

2 邻接表

表示方法

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

在这里插入图片描述

Tips:对于邻接表的表示方法,举个例子, v 1 v_1 v1之后的是3,这个3对应的是表中的下标,也就是 v 4 v_4 v4,不要直接认为3就是 v 3 v_3 v3

2.1 无向图的邻接表

在这里插入图片描述

边得双倍。怎么计算度?看到有几个表节点(紫色的点),就是有几个与其关联的边。所以,无向图中顶点 v i v_i vi的度为第 i i i个单链表中的结点数。

2.2 有向图的邻接表

在这里插入图片描述
特点:

  1. 顶点 v i v_i vi的出度为第 i i i个单链表中的结点个数。
  2. 顶点 v i v_i vi的入度为整个单链表中邻接点域值是 i − 1 i-1 i1的结点个数。

综上,找出度容易,入度难。

在这里插入图片描述
还有一个逆邻接表表示,这样就是找入度容易,找出度难

练习:已知某网的邻接(出边)表,请画出该网络
在这里插入图片描述
当邻接表的存储结构形成后,图便唯一确定。

2.3 邻接表的建立

在这里插入图片描述

#define MVNum 100 //最大顶点数
typedef struct VNode
{
    VerTexType data; //顶点信息
    ArcNode * firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList为邻接表

typedef struct ArcNode //边结点
{
    int adjvex; //该边所指向的顶点的位置
    struct ArcNode * nextarc; //指向下一条边的指针
    OtherInfo info; //和边相关的信息
}ArcNode;

typedef struct //图结构的定义
{
    AdjList vertices;//vertices -- vertex的复数
    int vexnum, arcnum; //图的当前顶点数与弧数
}ALGraph;

在这里插入图片描述
构建图G后,直接用成员变量进行赋值。

2.3.1 采用邻接表建立无向网

在这里插入图片描述

#define MVNum 100 //最大顶点数
typedef struct VNode
{
    VerTexType data; //顶点信息
    ArcNode * firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList为邻接表

typedef struct ArcNode //边结点
{
    int adjvex; //该边所指向的顶点的位置
    struct ArcNode * nextarc; //指向下一条边的指针
    OtherInfo info; //和边相关的信息
}ArcNode;

typedef struct //图结构的定义
{
    AdjList vertices;//vertices -- vertex的复数
    int vexnum, arcnum; //图的当前顶点数与弧数
}ALGraph;

//

Status CreateUDG(ALGraph &G) //采用邻接表表示法,创建无向图G
{
    cin >> G.vexnum >> G.arcnum; //输入总项点数,总边数
    for (i = 0; i < G.vexnum; ++i)//输入各点,构造表头结点表
    {
        cin >> G.vertices[i].data; //输入顶点值
        G.ertices[i].firstarc = NULL; //初始化表头结点的指针域
    }
    for (k = 0; k < G.arcnum; ++k) //输入各边,构造邻接表
    {
        cin >> v1 >> v2;    //输入一条边依附的两个顶点
        i = LocateVex(G, v1);
        j = LocateVex(G, v2);
        p1 = new ArcNode; //生成一个新的边结点*p1
        p1->adjvex = j; //邻接点序号为j
        p1->nextarc = G.vertices[i].firstarc;
        G.vertices[i].firstarc = p1;//将新结点*p1插入顶点vi的边表头部
        p2 = new ArcNode; //生成另一个对称的新的边结点*p2
        p2->adjvex = i; //邻接点序号为i
        p2->nextarc = G.vertices[j].firstarc;
        G.vertices[j].firstarc = p2; //将新节点*p2插入顶点vj的边表头部
    }
   return OK;
}

2.3.2 采用邻接表建立有向网

如果建立有向网,就只需要建立入度/出度的。

2.4 邻接表的特点

在这里插入图片描述

  • 无向图是 N + 2 E N+2E N+2E,有向图是 N + E N+E N+E
  • 无向图方便计算度,有向图方便计算出度,不方便入度,入度计算得靠逆邻接表。

3 邻接矩阵与邻接表的区别

3.1 联系

在这里插入图片描述

3.2 区别

在这里插入图片描述

邻接表因为节点插入顺序不同,导致不唯一。

4 改进的邻接表

在这里插入图片描述

4.1 十字链表—用于有向图

将邻接表与逆邻接表结合起来。
在这里插入图片描述
在这里插入图片描述
给表头结点再增加一个指针域,用来放入度边(因为有向图的邻接表算出度好算)
在这里插入图片描述
顶点节点:

  1. firstout表明第一条出弧(出度边)
  2. firstin表明第一条入弧(入度边)

弧节点:

  1. tailvex表明弧尾位置(出度时顶点是弧尾)
  2. headvex表明弧头位置(入度时顶点是弧头)
  3. hlink表明弧头相同的下一条弧(入度指向同一节点,找headvex相同的即可)
  4. tlink表明弧尾相同的下一条弧(出度从同一节点出发,找tailvex相同的即可)

在这里插入图片描述
以上就是十字链表,统计入度出度很方便。

4.2 邻接多重表

解决无向图每条边存储两遍的问题。
在这里插入图片描述
在邻接表当中,任意一条边,都会出现两次。
现在换成邻接多重表后,就记录好这个边是哪两个顶点之间的边就行了。

邻接多重表的结构,顶点节点与边结点的表示形式:
在这里插入图片描述

5 总结

以上便是图的存储结构,如有遗漏,欢迎评论区补充,感谢。

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

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

相关文章

Java将汉字转拼音以及判断字符是否为汉字

首先是将汉字转换为拼音&#xff1a; 导入依赖&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency>创建转拼音的静态方法toPinyin&#xf…

掌握 Python RegEx:深入探讨模式匹配

动动发财的小手&#xff0c;点个赞吧&#xff01; 什么是正则表达式&#xff1f; 正则表达式通常缩写为 regex&#xff0c;是处理文本的有效工具。本质上&#xff0c;它们由一系列建立搜索模式的字符组成。该模式可用于广泛的字符串操作&#xff0c;包括匹配模式、替换文本和分…

在线阅读版:《2023中国软件供应链安全分析报告》全文

聚焦源代码安全&#xff0c;网罗国内外最新资讯&#xff01; 专栏供应链安全 数字化时代&#xff0c;软件无处不在。软件如同社会中的“虚拟人”&#xff0c;已经成为支撑社会正常运转的最基本元素之一&#xff0c;软件的安全性问题也正在成为当今社会的根本性、基础性问题。 随…

火车头采集器伪原创【php源码】

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python中按钮的位置怎么摆放&#xff0c;python中按钮怎么设置颜色&#xff0c;现在让我们一起来看看吧&#xff01; 火车头采集ai伪原创插件截图&#xff1a; 1、用python的pygame,做一个按钮 唔...摁钮&#xff1f;…

【万字长文】SpringBoot整合SpringSecurity+JWT+Redis完整教程(提供Gitee源码)

前言&#xff1a;最近在学习SpringSecurity的过程中&#xff0c;参考了很多网上的教程&#xff0c;同时也参考了一些目前主流的开源框架&#xff0c;于是结合自己的思路写了一个SpringBoot整合SpringSecurityJWTRedis完整的项目&#xff0c;从0到1写完感觉还是收获到不少的&…

MYSQL导入excel数据后只显示500条

问题&#xff1a;明明显示数据全部导入成功&#xff0c;但是点开table后发现只显示了500条 解决步骤&#xff1a;&#xff08;以datagrip为例&#xff09; 其实大家已经把数据导入了&#xff0c;只是在工具里&#xff0c;它在设置里面做了限制&#xff0c;只显示500条数据。只…

Kotlin 内联函数语法之let、apply、also、run、with的用法与详解

一、介绍 kotlin的语法千奇百怪&#xff0c;今天我们将介绍项目中频率使用比较高的几个内联函数。 二、什么叫内联函数&#xff1f; 内联函数 的语义很简单&#xff1a;把函数体复制粘贴到函数调用处 。使用起来也毫无困难&#xff0c;用 inline关键字修饰函数即可。 语法&a…

三菱FX5U系列PLC内置定位功能的基本使用方法介绍

三菱FX5U系列PLC内置定位功能的基本使用方法介绍 三菱FX5U系列PLC本体自带的高速脉冲输出可以实现定位功能,具体的使用方法可参考以下内容: 参数设定 如下图所示,新建一个工程,在左侧的项目树中找到参数–模块参数—高速I/O,双击进入后找到输出功能—定位—点击进入详细设…

BHQ 1Mal,BHQ-1 Maleimide,BHQ1马来酰亚胺,黑洞猝灭剂

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ PART1----产品描述&#xff1a; BHQ-1 Maleimide黑洞猝灭剂-1(BHQ-1)被归类为暗猝灭剂&#xff0c;该淬灭剂能够将一定距离内荧光基团发出的光全部吸收&#xff0c;实现对荧光信号的淬灭&#xff0c;所以可得到更强的特异性…

基于SpringBoot+Vue的学习平台设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

神经网络的初始化方法

文章目录 1、随机初始化2、Xavier初始化3、He初始化4、权重预训练初始化5、零初始化 对于神经网络的训练过程中&#xff0c;合适的参数初始化方法有助于更好的处理梯度消失和梯度爆炸问题。通常有以下几种初始化方法&#xff1a; 1、随机初始化 随机初始化&#xff08;Random…

[JavaWeb]MySQL的安装与介绍

MySQL的安装与介绍 一.数据库相关概念1.1 数据库1.2 常见的关系型数据库管理系统 二.MySQL数据库1.MySQL的安装2.配置环境变量3.新建MySQL配置文件4.初始化MySQL5.注册MySQL的服务6.修改默认账户与密码7.连接MySQL服务8.MySQL的卸载 三.MySQL的数据模型1.关系型数据库 一.数据库…

static关键字和继承

1、static关键字 1.1案例题目 • 编程实现People类的封装&#xff0c;特征有&#xff1a;姓名、年龄、国籍&#xff0c;要求提供打印所有特征的方法。 • 编程实现PeopleTest类&#xff0c;main方法中使用有参方式构造两个对象并打印。 /*编程实现People类的封装*/ public cl…

Python+Texturepacker自动化处理图片

前言 本篇在讲什么 PythonTexturepacker自动化处理图片 本篇需要什么 对Python语法有简单认知 依赖Python2.7环境 依赖Texturepacker工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &…

ubuntu18.04 安装php7.4-xdebug

文章目录 场景解决 场景 apt install php7.4-xdebug 下载失败, 只好通过编译解决了 解决 https://xdebug.org/wizard 输入php -i的执行结果

mybatisplus映射解读

目录 自动映射 表映射 字段映射 字段失效 视图属性 Mybatis框架之所以能够简化数据库操作&#xff0c;是因为他内部的映射机制&#xff0c;通过自动映射&#xff0c;进行数据的封装&#xff0c;我们只要符合映射规则&#xff0c;就可以快速高效的完成SQL操作的实现。既然…

AI语音合成 VITS Fast Fine-tuning,半小时合成专属模型,部署训练使用讲解

前言 项目名&#xff1a;VITS-fast-fine-tuning &#xff08;VITS 快速微调&#xff09; 项目地址&#xff1a;https://github.com/Plachtaa/VITS-fast-fine-tuning 支持语言&#xff1a;中、日、英 官方简介&#xff1a; 这个代码库会指导你如何将自定义角色&#xff08;甚至…

低温试验中的液氮注入式宽温区超高精度温度控制解决方案

摘要&#xff1a;当前各种测试仪器中的低温温度控制过程中&#xff0c;普遍采用电增压液氮泵进行制冷和辅助电加热形式的控温方式。由于液氮温度和传输压力的不稳定&#xff0c;这种方式的控温精度仅能达到0.5K&#xff0c;很难实现小于0.1K的高精度控温。为此本文基于饱和蒸气…

知识梳理(一)

HTTPS握手过程 https的核心的技术&#xff1a;使用非对称加密传输对称加密的密钥&#xff0c;然后用对称加密通信 TLS http--超文本传输协议&#xff0c;是以前并且沿用至今的网页协议。 缺点&#xff1a;http属于明文传输 HTTP的明文传输带来的问题是无法防止中间人截获、…

VScode远程不用再输入密码操作

安装插件remote development 1.先检查自己电脑上有没有生成一对公钥和私钥。&#xff08;一般会在这个目录&#xff09; 如果没有的话就自己生成一下。 打开命令行输入以下命令 ssh-keygen -t rsa2.在虚拟机中先看一下有没有公钥和私钥。如果没有的话就自己生成一下。 打开…