数据结构学习笔记——多维数组、矩阵与广义表
目录
- 一、多维数组
- (一)数组的定义
- (二)二维数组
- (三)多维数组的存储
- (四)多维数组的下标的相关计算
- 二、矩阵
- (一)特殊矩阵和稀疏矩阵
- (二)对称矩阵
- (三)对角矩阵
- (四)稀疏矩阵的压缩存储
- 三、广义表
- (一)广义表的定义
- (二)广义表的表头和表尾
- (三)广义表的深度和长度
- (四)广义表表示二叉树
一、多维数组
(一)数组的定义
数组是由n(n≥1)个相同数据类型的数据元素组成的有限序列,在定义数组时,会为数组分配一个固定大小的内存空间,用来存储元素,数组在被定义后,其维度不可以被改变。
数组在确定其维度和维界后,元素的个数是固定的,所以不能进行插入和删除运算。数组中最常见的两种操作是查找和修改。
(二)二维数组
数组可分为一维数组和多维数组(常见的有二维数组),二维数组可以看作一维数组的一维数组。顺序表是一个一维数组,所以它是线性结构,与栈、队列、串的逻辑结构相同,而多维数组则是典型的非线性结构,也可以说它是嵌套的线性结构。
例如,一个二维数组A[3][4]在内存中实际上是一个长度为3的一维数组,每个元素是一个长度为4的一维数组,即对应三行四列,其中元素是从上到下、从左到右依次存储的,如下:
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 0 | [0,0] | [0,1] | [0,2] | [0,3] |
| 1 | [1,0] | [1,1] | [1,2] | [1,3] |
| 2 | [2,0] | [2,1] | [2,2] | [2,3] |
由于数组中是从下标0开始的,所以一个m行n列的二维数组中,最开始的元素是[0,0],最后的元素是[m-1,n-1],上面三行四列的二维数组A[3][4]中的最后一个元素即为[2,3]。
(三)多维数组的存储
二维数组的存储较一维数组不一样,有两种存储方式,可分为行优先存储和列优先存储,前者是先按每行存储满后再继续下一行,后者相反先按每列存储满后再继续下一列。
例如,定义一个二维数组A[3][3],在连续的内存空间里,如下:

若按照行优先存储,以A[2][0]为例,在存储A[2][0]之前,是这样存储的:

而按照列优先存储,以A[1][1]为例,在存储A[1][1]之前,是这样存储的:

(四)多维数组的下标的相关计算
设一个二维数组A[i][j],其中行下标和列下标的范围分别为[0,a]和[0,b],若每个数组元素在内存中占用L个存储单元,且数组中第一个元素的存储位置为LOC[c1][c2],求该二维数组中任意一元素A[i][j]的存储位置?
1、按行优先存储
【所求行乘列界限加1,然后加所求列确定位置】
(1)先确定有多少行,加上列数,然后乘以存储单元,最后加上第一个元素的存储位置,得:LOC[i][j]=LOC[c1][c2]+[(i-c1)×(b-c2+1)+(j-c2)]×L。
(2)若在编程语言中,由于数组元素下标是从0开始的,该式子改写为:LOC[i][j]=LOC[0][0]+[i×(b+1)+j]×L。
例、二维数组A[m][n]采用行序为主方式存储,每个元素占L个存储单位。元素A[0][0]的存储地址是b,求元素A[i][j](0 ≤ i ≤ m-1,0 ≤ j ≤ n-1)的存储地址。
解析:由于二维数组中行列元素都是从0开始的,即LOC[i][j]=b+[i×(n-1+1)+j]×L=b+[i×n+j]×L。
2、按列优先存储
【所求列乘行界限加1,然后加所求行确定位置】
(1)先确定有多少列,加上行数,然后乘以存储单元,最后加上第一个元素的存储位置,得:LOC[i][j]=LOC[c1][c2]+[(j-c1)×(a-c2+1)+(j-c1)]×L。
(2)若在编程语言中,由于数组元素下标是从0开始的,该式子改写为: LOC[i][j]=LOC[0][0]+[j×(a+1)+i]×L。
例、设7行6列的数组a以列序为主序顺序存储,基地址为1024,每个元素占2个存储单元,架设无第0行第0列,求第4行第5列的元素的存储地址。
解析:由于第一个元素为a[1][1],所以要减去后再代入计算,即
LOC[4][5]=1024+[(5-1)×(7-1+1)+(4-1)]×2=1024+62=1086。
- 对于一个数组An×n(方阵),其元素aij按行优先与按列优先存储时地址之差为(n-1)(i-j)。
二、矩阵
(一)特殊矩阵和稀疏矩阵
相同的元素或零元素在矩阵中的分布存在一定规律的矩阵称为特殊矩阵,反之则为稀疏矩阵。简单的来说,特殊矩阵既然特殊,说明其中有很多相同或者有零元素,且存在一定规律在矩阵中分布。
常见的特殊矩阵有对称矩阵、反对称矩阵、上/下三角矩阵、对角矩阵等等,例如对角矩阵中,只有对角线上有元素,其余元素均为零:

(二)对称矩阵
若一个方阵满足Ai×j=Aj×i,则称为对称矩阵。由于对称矩阵中上三角部分和下三角部分的元素对应相同,在存储对称矩阵时,为了避免空间的浪费,可以只存储上或下三角部分的元素,将其存放在一个一维数组中,该数组的大小为1+2+……+n=n(1+n)/2。
(三)对角矩阵
三对角矩阵就是一种对角矩阵,其中非零元素都集中在以主对角线为中心的三条对角线的区域中,其他区域均为零。
(四)稀疏矩阵的压缩存储
前面讲到,稀疏矩阵中非零元素的分布与特殊矩阵相反,是没有规律的。稀疏矩阵中大部分元素都为0,且与非零元素的分布一样,也是没有规律的。对矩阵压缩的目的是节省存储空间。
1、三元组表
为了压缩存储稀疏矩阵,在存储时不仅要存储矩阵中非零元素的值,同时还要存储该元素所在的行与列,从而组成一个三元组表(行、列、值),依此减少了存储空间。由于是将稀疏矩阵中的非零元素以及其对应的行、列号以三元组的形式存储在一个数组中,所以经过这种压缩存储后就无法通过数组的下标直接存取矩阵的元素,失去了随机存取的特性。另外,稀疏矩阵的三元组表也可以采用十字链表法存储。【稀疏矩阵的两种存储结构是三元组表(数组)和十字链表】
//以整型int为例,可替换其他类型
typedef struct{int i,j; //行与列int x; //值
}Sparsematrix;
例如,一个稀疏矩阵A,进行压缩存储:

对应的三元组表,如下:
| i(行) | j(列) | x(值) |
|---|---|---|
| 1 | 1 | 4 |
| 1 | 3 | 2 |
| 2 | 0 | 5 |
例如,有一个100×90的稀疏矩阵,非0元素有10个,设每个整型数占2字节,则用三元组表示矩阵时,求所需的字节数。
解析:三元组表包括行、列、值,每个整型数占2字节,所以10个非0元素占3×2×10=60字节,另外还有三元组表中行数、列数和总的非零元素个数共6个字节,一共60+6=66字节。
2、十字链表
十字链表法中,稀疏矩阵的行和列都用一个带头结点的链表表示,从而对应着五个分量:行、列、数据域、指向下方结点的指针和指向右方结点的指针,其结点的结构如下:

三、广义表
(一)广义表的定义
广义表是线性表的进一步推广,是由n(n≥0)个数据元素组成的有序序列。线性表中的数据元素只能是单个元素(原子),它是不可分割的,而广义表中的数据元素既可以是原子,也可以是一个广义表(包括空表和非空表),广义表通过圆括号“()”括起来,通过逗号“,”隔开表中的各个数据元素。

一个n维数组可以看成元素是n-1维数组的广义表,广义表的元素都是n-1维数组。另外,若广义表中的所有元素都是原子时,此时的广义表就是一个线性表。
(二)广义表的表头和表尾
广义表是可以递归的,一个广义表也可以是其自身的子表,广义表中的第一个元素称为广义表的表头,而剩余数据元素组成的表称为广义表的表尾,广义表的表头和表尾可以看作通过函数Head()和Tail()对广义表操作。任何一个非空广义表,表头可能是单个元素(原子)或广义表,但表尾只可能是广义表,其原因是广义表的取表尾Tail()是非空广义表除去表头元素后,剩余元素组成的表,所以不可能是原子。

例如,C=(a,b,c,d,e,f,g),该广义表的表头是(a),表尾是(b,c,d,e,f,g);
例如,D=((a,b),((c,d,e),(f,g,h))),该广义表的表头是(a,b),表尾是((c,d,e),(f,g,h))。
另外,若一个广义表为空,则为一个空表。例如,E=( ),F=(( )),广义表E是一个空表,只有非空广义表才能取表头,广义表F的表头和表尾都是()。
(三)广义表的深度和长度
- 广义表的深度通过
括号的层数求得,而长度是广义表中所含元素的个数。
例如,一个空广义表G=(),括号层数为1,所以广义表的深度为1,而由于是空表,所以广义表的长度为0;
例如,一个广义表H=((a,b),(c,(d,e))),括号层数为3,所以广义表的深度为3,最高层为(c,(d,e)),逗号隔开了原子( c )和广义表( d,e ),元素个数为2,所以广义表的长度为2。
例如,一个广义表I=((),(a),(b,c,(d),((d,f)))),由于括号的最大层数为4,所以广义表的深度为4,可知广义表有三个元素,分别是()、(a)、(b,c,(d),((d,f))),元素个数为3,所以广义表的长度为3。
例如,设广义表J=(( ),( )),对广义表J,head(J)=( ),Tail(J)=(( )),括号的最大层数为2,所以广义表的深度为2,广义表有两个元素,分别是()、(),元素个数为2,所以广义表长度为2。
注:这里的Tail(J)=(( )),而不是( )。
(四)广义表表示二叉树
根据广义表中“ 数据元素既可以是原子,也可以是一个广义表(包括空表和非空表) ”这一点可以来表示二叉树,即通过(根结点,根结点的广义表)的形式来表示,其中可以嵌套。
例如,下面是一个满二叉树:

通过广义表表示该二叉树:
(A , ( B , ( D , E ) ) , ( C , ( F , G ) ) ) )
这个二叉树的解释如下:
根结点是A,它的左孩子是B,B的左孩子是D,B的右孩子是E。
根结点A的右孩子是C,C的左孩子是F,C的右孩子是G。
相关文章:
数据结构学习笔记——多维数组、矩阵与广义表
目录 一、多维数组(一)数组的定义(二)二维数组(三)多维数组的存储(四)多维数组的下标的相关计算 二、矩阵(一)特殊矩阵和稀疏矩阵(二)…...
C++之常用的排序算法
C之常用的排序算法 sort #include<iostream> using namespace std; #include<vector> #include<algorithm> #include<functional> void Myptint(int val) {cout << val << " "; }void test() {vector<int> v;v.push_back(…...
Mac中LaTex无法编译的问题
最近在使用TexStudio时,遇到一个棘手的问题: 无法编译,提示如下: kpathsea: Running mktexfmt xelatex.fmt /Library/TeX/texbin/mktexfmt: kpsewhich -var-valueTEXMFROOT failed, aborting early. BEGIN failed–compilation a…...
【Python爬虫】8大模块md文档集合从0到scrapy高手,第7篇:selenium 数据提取详解
本文主要学习一下关于爬虫的相关前置知识和一些理论性的知识,通过本文我们能够知道什么是爬虫,都有那些分类,爬虫能干什么等,同时还会站在爬虫的角度复习一下http协议。 爬虫全套笔记地址: 请移步这里 共 8 章&#x…...
【python基础(三)】操作列表:for循环、正确缩进、切片的使用、元组
文章目录 一. 遍历整个列表1. 在for循环中执行更多操作2. 在for循环结束后执行一些操作 二. 避免缩进错误三. 创建数值列表1. 使用函数range()2. 使用range()创建数字列表3. 指定步长。4. 对数字列表执行简单的统计计算5. 列表解析 五. 使用列表的一部分-切片1. 切片2. 遍历切片…...
使用VSCode调试全志R128的C906 RISC-V核心
使用 VSCode 调试 调试 XuanTie C906 核心 准备工具 T-Head DebugServer(CSkyDebugServer) - 搭建调试服务器 下载地址:T-Head DebugServer手册:T-Head Debugger Server User Guide驱动:cklink_dirvers VSCode - 开…...
Node.js之http模块
http模块是什么? http 模块是 Node,js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的 http.createServer() 方法,就能方便的把一台普通的电脑,变成一台Web 服务器,从而对外提供 Web 资源服务。 如果我们想在node…...
golang 断点调试
1.碰见如下报错,调试器没有打印变量信息 Delve is too old for Go version 1.21.2 (maximum supported version 1.19) 2. 解决办法 升级delve delve是go语言的debug工具。 go install github.com/go-delve/delve/cmd/dlvlatest报错 Get “https://proxy.golang.org/github…...
定时器如何计算触发频率?
定时器触发频率的计算公式为:定时器时钟频率/(预分频系数*计数周期1)。其中,定时器时钟频率是指定时器所连接的总线频率,预分频系数和计数周期需要根据具体的需求进行设置。预分频系数用于将总线频率分频,计…...
【数据库】数据库中的检查点Checkpoint,数据落盘的重要时刻
检查点(checkpoint) 专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会定…...
关于 Docker
关于 Docker 1. 术语Docker Enginedockerd(Docker daemon)containerdOCI (Open Container Initiative)runcDocker shimCRI (Container Runtime Interface)CRI-O 2. 容器启动过程在 Linux 中的实现daemon 的作用 Docker 是个划时代的开源项目,…...
LeetCode解法汇总2342. 数位和相等数对的最大和
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 给你一个下…...
数据库的级联删除
级联删除是指在数据库中删除一个对象时,与该对象有关的其他对象也被自动删除。在 Django 中,级联删除通常通过在模型中定义外键时使用 on_delete 参数来实现。以下是一些常见的 on_delete 选项: 1.models.CASCADE: 当关联的对象被删除时&…...
【Python 千题 —— 基础篇】奇数列表
题目描述 题目描述 创建奇数列表。使用 for 循环创建一个包含 20 以内奇数的列表。 输入描述 无输入。 输出描述 输出创建的列表。 示例 示例 ① 输出: 创建的奇数列表为: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]代码讲解 下面是本题的代码: #…...
当npm下载库失败时可以用cnpm替代
下载cnpm npm install -g cnpm --registryhttp://registry.npmmirror.com 然后使用cnpm代替npm下载即可 cnpm install...
PyTorch多GPU训练时同步梯度是mean还是sum?
PyTorch 通过两种方式可以进行多GPU训练: DataParallel, DistributedDataParallel. 当使用DataParallel的时候, 梯度的计算结果和在单卡上跑是一样的, 对每个数据计算出来的梯度进行累加. 当使用DistributedDataParallel的时候, 每个卡单独计算梯度, 然后多卡的梯度再进行平均.…...
Spring Framework IoC依赖注入-按Bean类型注入
Spring Framework 作为一个领先的企业级开发框架,以其强大的依赖注入(Dependency Injection,DI)机制而闻名。DI使得开发者可以更加灵活地管理对象之间的关系,而不必过多关注对象的创建和组装。在Spring Framework中&am…...
IDEA运行thymeleaf的html文件打开端口为63342且连不上数据库
这边贴apple.html代码 <!DOCTYPE html> <html xmlns:th"http://www.thymeleaf.org"> <head><meta charset"UTF-8"><title>User List</title> </head> <body> <h1>User List</h1> <table&…...
sql报错注入和联合注入
1.[NISACTF 2022]join-us 过滤: as IF rand() LEFT by updatesubstring handler union floor benchmark COLUMN UPDATE & sys.schema_auto_increment_columns && 11 database case AND right CAST FLOOR left updatexml DATABASES BENCHMARK BY sleep…...
028 - STM32学习笔记 - ADC结构体学习(二)
028 - STM32学习笔记 - 结构体学习(二) 上节对ADC基础知识进行了学习,这节在了解一下ADC相关的结构体。 一、ADC初始化结构体 在标准库函数中基本上对于外设都有一个初始化结构体xx_InitTypeDef(其中xx为外设名,例如…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
