[入门必看]数据结构6.2:图的存储及基本操作

news2024/11/16 17:55:48

[入门必看]数据结构6.2:图的存储及基本操作

  • 第六章 图
  • 6.2 图的存储及基本操作
    • 知识总览
      • 6.2.1 邻接矩阵法
      • 6.2.2 邻接表法
      • 6.2.3+6.2.4 十字链表、邻接多重表
      • 6.2.5 图的基本操作
    • 6.2.1 邻接矩阵法
      • 图的存储——邻接矩阵法
      • 邻接矩阵法存储带权图(网)
      • 邻接矩阵法的性能分析
      • 邻接矩阵法的性质
    • 6.2.2 邻接表法
      • 邻接表法(顺序+链式存储)
    • 6.2.3+6.2.4 十字链表、邻接多重表
      • 十字链表存储有向图
      • 十字链表法性能分析
      • 邻接多重表存储无向图
    • 6.2.5 图的基本操作
      • Adjacent(G,x,y):判断图G是否存在边<x, y>或(x, y)
      • Neighbors(G,x):列出图G中与结点x邻接的边
      • InsertVertex(G,x):在图G中插入顶点x
      • DeleteVertex(G,x):从图G中删除顶点x
      • AddEdge(G,x,y):若无向边(x, y)或有向边<x, y>不存在,则向图G中添加该边
      • RemoveEdge(G,x,y):若无向边(x, y)或有向边<x, y>存在,则从图G中删除该边
      • FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1
      • NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
      • Get_edge_value(G,x,y):获取图G中边(x, y)或<x, y>对应的权值。
      • Set_edge_value(G,x,y,v):设置图G中边(x, y)或<x, y>对应的权值为v。
  • 知识回顾与重要考点
    • 6.2.1 邻接矩阵法
    • 6.2.2 邻接表法
    • 6.2.3+6.2.4 十字链表、邻接多重表
    • 6.2.5 图的基本操作


第六章 图

小题考频:33
大题考频:11


6.2 图的存储及基本操作

难度:☆☆☆☆

知识总览

6.2.1 邻接矩阵法

在这里插入图片描述


6.2.2 邻接表法

在这里插入图片描述


6.2.3+6.2.4 十字链表、邻接多重表

在这里插入图片描述


6.2.5 图的基本操作

在这里插入图片描述


6.2.1 邻接矩阵法

在这里插入图片描述

图的存储——邻接矩阵法

在这里插入图片描述

1表示两个顶点相互邻接
0表示两个顶点相互不邻接

实现:
在这里插入图片描述

定义一个一维数组存放各个顶点的信息。
——用char类型可以放置更复杂的数据。

用二维数组表示各个边的信息。
——因为此处边只有0和1两种状态,可以使用空间更小的bool类型或者枚举类型。
(int型变量可能会占4B或8B,而bool类型或者枚举类型只占1B)

各个结点的数据在数组中有一个具体的编号,Eg.A-0、B-1、C-2……
利用结点在数组中的下标和邻接矩阵里行和列进行对应。

在这里插入图片描述

如果矩阵中某一个元素为1,意味着与之对应的边或弧存在,为0则不存在。

在这里插入图片描述

无向图:
第i个结点的=第i行(或第i列)的非零元素个
操作复杂度为 O ( n ) O(n) O(n)

Eg. 要求结点B的度,检查和B对应的这一行,总共有几个非0元素。
可以看到有3个,所以B的度就应该是3。

有向图:
第i个结点的出度=第i行的非零元素个数
第i个结点的入度=第i列的非零元素个数
第i个结点的=第i行、第i列的非零元素个数之和


邻接矩阵法存储带权图(网)

在这里插入图片描述

带权图:在对应的位置写上两个顶点之间对应的权值。
如果两个顶点之间不存在边,用无穷表示。

可以定义一个常量INFINITY,取int值的最大值来表示无穷
边的权值可以根据场景改为其他类型

在这里插入图片描述

有时带权图中,会把自己指向自己的这条边的权值设为0
在带权图中,如果一条边是无∞或0,则表示与之对应的两个顶点之间不存在边


邻接矩阵法的性能分析

在这里插入图片描述
 
空间复杂度: O ( ∣ V ∣ 2 ) O(|V|^2) O(V2)——只和顶点数相关,和实际的边数无关

适合用于存储稠密图

如果一个图中顶点数很多,边数很少,那么邻接矩阵中会有很多空间被浪费。

无向图的邻接矩阵是对称矩阵,可以压缩存储(只存储上三角区/下三角区)

回顾:对称矩阵的压缩存储在这里插入图片描述


邻接矩阵法的性质

——此处讨论的为不带权图

在这里插入图片描述
设图G的邻接矩阵为 A A A(矩阵元素为0/1),则 A n A^n An的元素 A n [ i ] [ j ] A^n\left[ i \right] \left[ j \right] An[i][j]等于由顶点 i i i到顶点 j j j的长度为 n n n的路径的数目

此处 A A A指的是整个邻接矩阵(右图),其中的某个元素表示由顶点 i i i到顶点 j j j的长度为 n n n的路径的数目。

在这里插入图片描述

如果两个矩阵相乘的意义是什么?

Eg. A 2 [ 1 ] [ 4 ] A^2\left[ 1 \right] \left[ 4 \right] A2[1][4]:第一行和第四列分别相乘相加(式1)
现实意义:
Eg1. 如乘式中的元素 a 1 , 2 a_{1,2} a1,2为1,意义是结点A到结点B之间有一条边;
与之相乘的元素 a 2 , 4 a_{2,4} a2,4为1,意义是结点B到结点D之间有一条边;
相乘值为1,意义是存在1条可以从A到B到D的路径。
 
Eg2. 乘式中 a 1 , 3 a_{1,3} a1,3为0,表示从A到C没有路径;
a 3 , 4 a_{3,4} a3,4为0,表示从C到D没有路径;
相乘值为0,那么表示从A到C到D的路径就不存在

所以整个 A 2 [ 1 ] [ 4 ] = 1 A^2\left[ 1 \right] \left[ 4 \right] = 1 A2[1][4]=1的意义为,从结点A到结点D,只有1条长度为2的路径【A-B-D】
在这里插入图片描述

类似, A 2 [ 2 ] [ 2 ] = 3 A^2\left[ 2 \right] \left[ 2 \right] = 3 A2[2][2]=3,B到B有3条长度2的路径【BAB、BCB、BDB】
在这里插入图片描述

其余分析方法同上。

该矩阵 A 2 A^2 A2的含义为:矩阵中对应的两个结点之间长度为2的路径有多少条

在这里插入图片描述

三次方含义类似。
即对应结点之间长度为3的路径有多少条。

更严谨的证明方法详见离散数学图论部分。


6.2.2 邻接表法

在这里插入图片描述
邻接矩阵(顺序存储)的缺点是:空间复杂度高,为 O ( n 2 ) O(n^2) O(n2),不适合存储稀疏图。

邻接表法(顺序+链式存储)

在这里插入图片描述

用一个一位数组存储各个顶点信息:数据域,指向该顶点的第一条边/弧的指针
声明图时,声明顶点结点的一个数组,记录图中共有多少结点、多少边/弧。

对于各边/弧,也有一个与之对应的结点,int adjvex指明了当前这条边/弧指向哪个结点。
——Eg. 如图:AB相连,B的编号为1,所以A之后有一条指向1(结点B)的边,同时也有指向2(结点C)、3(结点D)的边
在这里插入图片描述
如果存储带权图,也可以在和边相关的这个顶点中加入权值信息。

对比:树的孩子表示法
在这里插入图片描述

邻接表法与树的孩子表示法是相似的

也可以用邻接表法存储有向图:
在这里插入图片描述

无向图中,两个相邻的结点会有相同的边。
所以无向图中,边的数据存在冗余:边
结点的数量是 2 ∣ E ∣ 2|E| 2∣E,整体空间复杂度为 O ( ∣ V ∣ + 2 ∣ E ∣ ) O(|V| + 2|E|) O(V+2∣E)

有向图中每个结点后的信息表示:从该结点往外射的一条弧
边结点的数量是 ∣ E ∣ |E| E,整体空间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(V+E)

在这里插入图片描述

无向图的度:遍历和结点相关的边链表,有多少边,度就是多少。
遍历边链表也可以找到该结点相连的所有边。

有向图的度:入度加上出度
出度:遍历和结点相关的边链表,有多少弧,度就是多少。
入度:唯一的办法就是把所有结点的边列表遍历一次,找指向那个结点的弧的数量

在这里插入图片描述

对于一个邻接表,表示方式不唯一。
边在链表中出现的先后顺序是任意的。

而邻接矩阵的表示方式是唯一的!

总结:
在这里插入图片描述


6.2.3+6.2.4 十字链表、邻接多重表

在这里插入图片描述

邻接矩阵、邻接表存储有向图都有所不便:

在这里插入图片描述

十字链表存储有向图

在这里插入图片描述

每一个结点对应一个编号.

十字链表法存储图,定义两个结构体:顶点结点和弧结点

图中顶点结点处的绿色箭头代表该顶点作为弧尾的第一条弧,弧结点的绿色箭头代表弧尾相同的下一条弧
Eg. ①0指向1 A->B ②0指向2 A->C
可以找到所有从当前顶点往外发射的弧

图中顶点结点处的橙色箭头代表该顶点作为弧头的第一条弧,弧结点的橙色箭头代表弧头相同的下一条弧
Eg. ①2指向0 C->A ②3指向0 D->A
可以找到所有指向当前结点的弧

十字链表法找出和入都很方便!

十字链表法性能分析

在这里插入图片描述

空间复杂度为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E),和邻接表同样优秀

如何找到指定顶点的所有出边?——顺着绿色线路找
如何找到指定顶点的所有入边?——顺着橙色线路找

注意:十字链表只用于存储有向图

对无向图的存储能否优化?
在这里插入图片描述

邻接矩阵:空间复杂度高
邻接表:数据冗余


邻接多重表存储无向图

在这里插入图片描述

看图,与十字链表相似
可以定义顶点结点、边结点结构体。
顶点结点:用数组的形式来顺序存储顶点信息。
顶点结点指针:指向和当前顶点相连的第一条边。
边结点:顺着iLink指针往下找,可以找到与当前顶点相连的下一条边。接下来没有更多边与当前顶点相连了,iLink指向NULL。

不用维护两份冗余数据,在删除结点和边的时候操作更方便。

  1. 删除边:
    在这里插入图片描述

删除边AB:

需要修改两个指针:让两个节点的指针指向后一条边

  1. 删顶点:
    在这里插入图片描述

删除顶点E:

除了删除顶点本身的信息之外,还需要删除和顶点相连的所有边的信息。
并修改指针的值。

更好的空间复杂度,没有冗余边。
删除边、节点都方便。
注意:只适用于存储无向图。


6.2.5 图的基本操作

在这里插入图片描述
在这里插入图片描述

Adjacent(G,x,y):判断图G是否存在边<x, y>或(x, y)

在这里插入图片描述
在这里插入图片描述

<>表示有向边(弧);()表示无向边

Neighbors(G,x):列出图G中与结点x邻接的边

在这里插入图片描述
在这里插入图片描述

InsertVertex(G,x):在图G中插入顶点x

在这里插入图片描述

DeleteVertex(G,x):从图G中删除顶点x

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AddEdge(G,x,y):若无向边(x, y)或有向边<x, y>不存在,则向图G中添加该边

在这里插入图片描述

RemoveEdge(G,x,y):若无向边(x, y)或有向边<x, y>存在,则从图G中删除该边

在这里插入图片描述

FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1

在这里插入图片描述
在这里插入图片描述

NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1

在这里插入图片描述

Get_edge_value(G,x,y):获取图G中边(x, y)或<x, y>对应的权值。

Set_edge_value(G,x,y,v):设置图G中边(x, y)或<x, y>对应的权值为v。

在这里插入图片描述


知识回顾与重要考点

6.2.1 邻接矩阵法

在这里插入图片描述
邻接矩阵法要点回顾:

  • 如何计算指定顶点的度、入度、出度(分无向图、有向图来考虑)?时间复杂度如何?
  • 如何找到与顶点相邻的边(入边、出边)?时间复杂度如何?
  • 如何存储带权图?
  • 空间复杂度—— O ( ∣ V ∣ 2 ) O(|V|^2) O(V2),适合存储稠密图
  • 无向图的邻接矩阵为对称矩阵,如何压缩存储?
  • 设图G的邻接矩阵为A(矩阵元素为0/1),则An的元素An[i][j]等于由顶点i到顶点j的长度为n的路径的数目

6.2.2 邻接表法

在这里插入图片描述

  • 空间复杂度:邻接表空间复杂度低【适合存储稀疏图】;邻接矩阵时间复杂度高【适合存储稠密度】
  • 表示方式:邻接表表示方式不唯一;邻接矩阵表示方式唯一‘
  • 计算度/入度/出度:邻接表计算有向图的度、入度不方便;邻接矩阵必须遍历对应行或列
  • 找相邻边:邻接表找有向图的入边不方便;邻接矩阵必须遍历对应行或列

6.2.3+6.2.4 十字链表、邻接多重表

在这里插入图片描述

  • 理解特性。
  • 十字链表只能存有向图
  • 邻接多重表只能存无向图

6.2.5 图的基本操作

在这里插入图片描述

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

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

相关文章

OpenAI再建顶级团队,重金招聘核心岗成员,阻止超级AI的威胁!

“AI确实可能会杀死人类。”这并不是哪家自媒体为博人眼球而发表的谣言&#xff0c;而是ChatGPT之父、OpenAI CEO山姆奥尔特曼在今年3月与MIT研究科学家Lex Fridman对话时亲口所说的一句话。 如今&#xff0c;这位全世界最受瞩目的老板决定采取行动&#xff0c;以阻止自己的预…

【算法】AcWing算法基础课笔记 第一章 基础算法 Part 1

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;AcWing &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对你…

Python程序设计基础:列表与元组(一)

文章目录 一、列表的表示与访问1、列表的表示2、列表的访问 二、列表的元素操作1、元素的修改2、元素的增加3、元素的删除4、其他操作 三、列表操作1、列表的遍历2、列表的排序3、列表的切片4、列表的扩充5、列表的复制6、列表的删除 一、列表的表示与访问 1、列表的表示 列表…

自营外卖配送平台的商家如何对接第三方美饿的订单

自营外卖跑腿平台对接第三方美饿的好处 单说美团饿了么自身的流量优势&#xff0c;很多商家不能忽视&#xff0c;但是美团饿了么的高额配送成本与抽成&#xff0c;同样也不能忽视。很多商家希望选择自配送或者其他更划算的配送方式来节省成本。这时&#xff0c;区域性的自建外…

【Java】单例模式

单例模式 设计模式概述单例模式实现思路饿汉式懒汉式饿汉式 vs 懒汉式 设计模式概述 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式免去我们自己再思考和摸索。就像是经典的棋谱&#xff0c;不同的棋局&#xff0c;我…

AttributeError: module ‘collections‘ has no attribute ‘Iterable‘

vitables 出现 AttributeError: module collections has no attribute Iterable错误修改如下图&#xff1a;

PCIE转PMC载板

描述 这是一款被动适配卡&#xff0c;它支持通过要转换为 PCIe x4 通道边缘连接器的 AMC 接头&#xff0c;来选择 TI EVM&#xff1b;因此它可被插入一个台式计算机或使用 PCIe 接头的任何位置。选定的 TI EVM 支持 DSP 上的本地 PCIe。此卡作为适配器&#xff0c;需要可与 AMC…

Linux与Windows:操作系统的比较与技巧分享

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Java 动态规划 Leetcode 62. 不同路径

代码展示&#xff1a; class Solution {public int uniquePaths(int m, int n) {//定义dp数组//二维数组多增加一行一列&#xff0c;方便对数组进行初始化int[][]dpnew int[m1][n1];//初始化dp[0][1]1;//填充数组for(int i1;i<m;i){for(int j1;j<n;j){dp[i][j]dp[i-1][j…

@Around踩坑记录

Around踩坑记录 先上结论&#xff1a; 如果你在定义切面的时候打算使用环绕通知➕定义注解的方式&#xff0c;那么在进行*Around*("(annotation(costTrace))") 类似这样的定义的时候&#xff0c;”costTrace“一定要与你定义切面中入参的参数名字一致&#xff0c;而…

【嵌入式Qt开发入门】Qt如何使用多线程——初识QThread

我们写的一个应用程序&#xff0c;应用程序跑起来后一般情况下只有一个线程&#xff0c;但是可能也有特殊情况。比如我们前几篇的例程都跑起来后只有一个线程&#xff0c;就是程序的主线程。线程内的操作都是顺序执行的。但试着想一下&#xff0c;我们的程序顺序执行&#xff0…

模拟日志数据

模拟日志数据。。 日志模拟器主要模拟站点的用户信息和用户行为日志数据 使用shell调用java类实现数据的生产 ! 所需文件如下: datagen.jar genlog.sh 注意: 存储数据的文件夹要预先创建好 Bash mkdir -p /tmp/doit/user_data mkdir -p /tmp/doit/log_data 将用来模拟生成…

【安全】Xsslabs(1~13)基于白盒测试浅析

目录 环境 关卡 level 1 level 2 level 3 level 4 level 5 level 6 level 7 level 8 扩展 level 9 level 10 level 11 level 12 level 13 总结 环境 PHP&#xff1a;php7.3.4nts 中间件&#xff1a;Nginx1.15.11 工具&#xff1a;Hackbar 关卡 level …

超长上下文处理:基于Transformer上下文处理常见方法梳理

原文链接&#xff1a;芝士AI吃鱼 目前已经采用多种方法来增加Transformer的上下文长度&#xff0c;主要侧重于缓解注意力计算的二次复杂度。 例如&#xff0c;Transformer-XL通过缓存先前的上下文&#xff0c;并允许随着层数的增加线性扩展上下文。Longformer采用了一种注意力…

【GLBCXX_3.4.21 not found】问题解决

问题描述 rootlocalhost:/home# rar -h rar&#xff1a;/lib64/libstdc.so.6 ,version "GLBCXX_3.4.21" not found 问题排查过程 下载相应的GCC源码&#xff0c;找到适合自己版本&#xff0c;这里选择是的是7.3.0 gcc源码下载地址&#xff1a;http://ftp.gnu.org/g…

fastadmin数据内容admin_id权限

/*** 是否开启数据限制* 支持auth/personal* 表示按权限判断/仅限个人* 默认为禁用,若启用请务必保证表中存在admin_id字段*/protected $dataLimit true;/*** 数据限制字段*/protected $dataLimitField admin_id;

第一次上传GitHub代码------教程、记录和踩雷

刚录用的一篇论文&#xff0c;编辑要求上传GitHub repo。 对于上传代码&#xff0c;本人是一无所知&#xff0c;写这篇博客记录一下 一. 创建代码仓库 点击右上角&#xff0c;选择New repository&#xff0c;来创建仓库&#xff1a; 根据提示&#xff0c;填写仓库的名称、描述…

TCP 协议(二)连接与断开

TCP 连接概述 TCP 协议是一种面向连接的、可靠的数据传输协议&#xff0c;同时 TCP 连接是全双工的&#xff0c;即连接的两端可以互传数据。在深入了解 TCP 连接之前&#xff0c;我们先来弄清楚整个 TCP 连接的过程&#xff0c;之后在深入整个数据报文结构来认识 TCP。 TCP连…

全网最全,adb常用命令大全(详细)全覆盖,看这篇就够了..

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 adb 模拟按键输入…

python subprocess执行外部命令常用方法

subprocess模块是Python标准库中的一个模块&#xff0c;用于创建和控制子进程。它提供了一种在Python程序中调用其他外部命令、执行系统命令和与系统进程进行交互的方法。常用的有两种方法&#xff1a;subprocess.run()&#xff0c;subprocess.Popen() 1. subprocess.run()方法…