1. 多维数据结构在软考中的位置与备考策略
软考软件设计师(中级)的数据结构部分,常被考生当成“背定义、记代码”的模块来处理,但真题做多了就会发现,数组、矩阵压缩、广义表这三个考点,恰恰是上午题(选择题)中“看似简单,实则陷阱密集”的区域。尤其是数组存储地址计算和矩阵压缩后的下标映射,几乎每年都考,而且年年都有不少人在这里丢分。
先说清楚这几块内容到底解决什么问题。数组是最基础的内存连续存储结构,要搞清楚的是“给定下标,元素存在哪个地址”,以及“给定地址,反推下标”这两类计算题。矩阵压缩则是利用矩阵中相同元素或零元素的分布规律,把二维数据“压”进一维数组,省内存的同时,必须能快速完成下标互换。广义表则是线性表的推广,允许元素本身又是一个表,考试重点在表头、表尾的递归定义、长度与深度的计算,以及存储结构的理解。
这三块内容为什么值得单独写一篇全解?因为它们在软考大纲里属于“数据结构基础”,但不是简单地背几个公式就能过关。你需要理解行优先、列优先的本质,要会推导对称矩阵、三角矩阵的压缩映射公式,还要能快速判断广义表的表头表尾。下面我会按真题的出题逻辑,把每个考点的原理、公式、推演过程、易错点全部拆开讲,顺带附上我自己刷题和复盘时整理出来的速记方法。
2. 数组存储与地址计算:行优先和列优先必须形成肌肉记忆
2.1 数组内存分配的底层逻辑
在讲地址计算之前,先建立一个底层认知:数组在内存中是一段连续空间。所谓连续,意思是每个元素占用的存储单元长度相同,且元素之间没有空隙。比如一个int数组,每个元素占4字节,那么第i个元素的地址就是首地址 + i * 4。这个逻辑看起来简单,但软考经常在里面加“干扰项”,比如告诉你数组下标从1开始,或者从0开始,还告诉你每个元素占多少个存储单元。
多维数组的存储方式只有两种:行优先和列优先。行优先就是先存完第一行的所有元素,再存第二行;列优先则是先存完第一列的所有元素,再存第二列。C语言默认行优先,Fortran默认列优先。软考题目里通常会明确说明采用哪种方式,但如果没说明,默认按行优先处理。
要理解这两种方式的本质区别,可以用“铺地板”来类比。行优先像是一排一排地贴瓷砖,贴完第一排再贴第二排;列优先像是一列一列地贴,贴完第一列再贴第二列。对于同一个二维数组,两种方式下,某个元素前面“已经贴了多少块砖”是不同的,这就是地址计算公式的差别所在。
2.2 一维数组与二维数组的地址公式推导
一维数组的地址计算几乎没有难度,但软考会把它和指针、下标范围结合起来考。设数组A[0..n-1],每个元素占L个存储单元,首地址为LOC(a0),那么LOC(ai) = LOC(a0) + i * L。如果数组下标是从1开始,则LOC(ai) = LOC(a1) + (i-1) * L。你需要做的,就是把“下标从几开始”这个条件刻在脑子里,因为它直接决定公式里是i还是i-1。
二维数组稍微复杂一点。设数组A[0..m-1][0..n-1],行优先存储时,元素A[i][j]的地址计算公式是:
LOC(A[i][j]) = LOC(A[0][0]) + (i * n + j) * L其中n是每行的元素个数,即列数。如果下标从1开始,公式变成:
LOC(A[i][j]) = LOC(A[1][1]) + ((i-1) * n + (j-1)) * L列优先存储时,元素A[i][j]的地址是:
LOC(A[i][j]) = LOC(A[0][0]) + (j * m + i) * L其中m是行数。注意,列优先是要看“前面有多少列”,每列有m个元素,所以在j上乘m。
这里有一个真题常考的变形:不是直接给你两个下标,而是给你一个一维数组的下标,让你反推二维下标。比如,按行优先存储的A[1..8][1..10],问第20个元素是哪个?这种题的解法是,先算偏移量,即20-1=19,然后做除法和取余。19 ÷ 10 = 1余9,所以行偏移为1、列偏移为9,对应A[2][10]。这个技巧叫“偏移量反推下标法”,一旦会用,几乎能秒杀所有同类题。
2.3 地址计算题的5个常见陷阱
地址计算题丢分,很少是因为不会公式,多半是栽在细节上。我复盘了近五年的真题,发现高频陷阱集中在以下几个方面:
第一个陷阱是忽略数组下标起始值。题目写A[1..n]还是A[0..n-1],公式完全不同。很多考生习惯性地用从0开始的公式,结果算出来的地址差了一个L。
第二个陷阱是混淆行数和列数。行优先公式里乘的是列数,不是行数。比如A[3][4],行优先的A[2][3]前面有2*4+3=11个元素,而不是2*3+4=10。这个错误特别隐蔽,因为一旦题目行列数相差不大,算出来的结果可能“看起来差不多”。
第三个陷阱是把数组元素大小和存储单元长度混为一谈。题目说“每个元素占2个存储单元”,那么L=2;但如果不幸看到“每个元素占4字节”而数组以字(Word)为编址单位,那么L=1(因为一个元素占1个字)。需要仔细甄别编址单位。
第四个陷阱是二维数组的“列优先”考法。很多考生只练了行优先,看到列优先就直接用行优先公式,结果错得离谱。应对方法很简单,只要记住:行优先乘列数,列优先乘行数。
第五个陷阱是求整个数组占用的存储空间。这时不是算某个元素的地址,而是算从首地址到末地址的差,再加上一个元素大小。公式为总字节数 = 元素总数 × L,也可以写成末地址 - 首地址 + L。如果问“最后一个元素的地址”,不要忘了它是首地址 + (元素总数-1) * L,不是首地址 + 元素总数 * L。
提示:做这类题时,我习惯先在草稿纸上写下“行数、列数、起始下标、L、存储方式”五个要素,再开始套公式。这样做能大幅降低看错题的概率。
3. 矩阵压缩存储:二维关系如何映射到一维空间
3.1 压缩存储的适用场景:特殊矩阵与稀疏矩阵
不是所有矩阵都需要压缩。软考考的是两类:一类是特殊矩阵,即元素分布有规律可循的矩阵,比如对称矩阵、三角矩阵、对角矩阵;另一类是稀疏矩阵,即零元素特别多的矩阵(通常认为非零元素个数占比小于5%时称为稀疏矩阵)。
特殊矩阵的压缩思路是“只存有用的元素”,把二维矩阵的下标映射到一维数组的下标。这种映射必须是可逆的,也就是说,从(i,j)能推出k,从k也能反推出(i,j)。软考考查的重点就是这两个方向的推导。
稀疏矩阵的压缩思路则完全不同。它只存储非零元素的行号、列号和值,也就是三元组(row, col, value),同时还要记录矩阵的总行数和总列数,否则无法还原。稀疏矩阵在软考中通常以三元组表的形式出现,偶尔会考十字链表的结构,但三元组更常考。
3.2 对称矩阵的压缩公式与下标互推
对称矩阵的特点是A[i][j] = A[j][i],所以只需要存储上三角或下三角(含对角线)的元素,就能还原整个矩阵。假设矩阵是n × n,按行优先存储下三角(含对角线)元素,则元素总数为n(n+1)/2。
下三角元素A[i][j](其中i ≥ j)在一维数组中的下标k计算方法是:先算前面0到i-1行有多少个元素,第p行(p从0开始)有p+1个元素,所以前i行元素总数为i(i+1)/2;再加上当前行中,A[i][j]是该行的第j个元素(j从0开始),于是:
k = i(i+1)/2 + j如果矩阵下标从1开始,那么A[i][j](i ≥ j)的下标公式是:
k = i(i-1)/2 + j - 1这里需要特别注意:一维数组的下标通常从0开始,但真题里也可能从1开始,要看清题目条件。
上三角元素A[i][j](i < j)怎么处理?利用对称性,把它映射成A[j][i],再套下三角的公式即可。即:
k = j(j+1)/2 + i (下标从0开始)反过来,从一维数组下标k反推二维下标(i,j),是软考中偏难的考法。思路是:找最大的i使得i(i+1)/2 ≤ k,那么行号就是i,列号就是k - i(i+1)/2。这个逆向过程需要一定的数学敏感度,我在后面会给出具体例题演示。
3.3 三角矩阵和对角矩阵的压缩方法
三角矩阵分上三角和下三角。下三角矩阵的压缩方式和对称矩阵几乎一样,但不是每个元素都能通过对称性还原。因为三角矩阵的另一半全是常数c(通常是0),所以存储时除了n(n+1)/2个下三角元素外,还要额外存一个常数c。也就是说,一维数组的总长度是n(n+1)/2 + 1。下三角矩阵A[i][j](i ≥ j)的映射公式与对称矩阵相同,而i < j时,所有元素都对应那个常数c。
上三角矩阵的压缩稍微绕一点。按行优先存储上三角(含对角线),第p行(p从0开始)有n-p个元素,前i行元素总数为n + (n-1) + ... + (n-i+1) = i(2n - i + 1)/2。元素A[i][j](i ≤ j)在其所在行中排第j-i个,所以:
k = i(2n - i + 1)/2 + (j - i)对角矩阵就简单多了,常见的三对角矩阵,只有主对角线及其上下相邻的两条对角线上的元素非零。软考考查的重点是“给定(i,j),判断是否在三条对角线上”,即|i - j| ≤ 1时是有效元素,否则是0。三对角矩阵的压缩通常按行优先存储这三条对角线上的元素,每条对角线上的元素个数不同,公式会更复杂一些,但真题里通常只要求判断元素是否为0,以及总存储量的大致估算。
3.4 稀疏矩阵的三元组表示与十字链表
稀疏矩阵的三元组表示法,本质上是把“矩阵”这个二维结构,翻译成一张“只记录非零元素”的线性表。每个三元组包含三个字段:行号、列号、值。存储时,通常还有两个额外信息:矩阵的行数、列数,以及非零元素的个数。
软考对三元组的考法主要有三种:第一种是给你一个稀疏矩阵,让你写出它的三元组表;第二种是给你三元组表,让你还原矩阵;第三种是考三元组表的转置操作,即交换行号和列号,并重新排序。
三元组表的转置有一个经典算法:先统计原矩阵每一列中非零元素的个数,再算出每一列第一个非零元素在转置后三元组表中的起始位置,最后扫描原三元组表,按照“列号从小到大”的顺序放入转置后的数组。这个算法的时间复杂度是O(n + t),其中n是列数,t是非零元素个数,比直接扫描矩阵找非零元素再逐个转置要高效得多。
十字链表法在软考中出现频率不高,但偶尔会在上午题中以概念题出现。它把每一行和每一列分别用一条链表串起来,每个非零元素节点同时挂在行链表和列链表上。十字链表的优势是插入和删除操作更灵活,不用像三元组表那样移动大量元素,但结构更复杂。软考只要求掌握结构图的识别和基本概念,不需要实现。
注意:稀疏矩阵的三元组表,元素的排列顺序通常按行优先排序,也就是先按行号从小到大,行号相同时按列号从小到大。转置后为了保持这个顺序,需要重新排列,这正是前面说的经典算法要解决的问题。
4. 广义表:表中有表的递归结构,如何准确拆解
4.1 广义表的定义与基础操作
广义表是线性表的推广,线性表中的元素必须是单个数据元素,而广义表中的元素可以是单个元素,也可以是一个广义表。比如A = (a, (b, c), d)就是一个广义表,它的第二个元素是子表(b, c)。
广义表用大写字母表示表名,用小写字母表示原子(单个数据元素)。原子的深度为0,空表的深度为1,非空表的深度等于“括号嵌套的最大层数”。比如(a, (b, (c)))的深度是3。
广义表有两个基本操作:取表头(Head)和取表尾(Tail)。表头是广义表的第一个元素,它可以是原子,也可以是子表;表尾是除去第一个元素后,剩余元素组成的表。注意,表尾一定是一个表,即使只有一个元素,它也是一个表的形式。比如(a, b, c)的表头是a,表尾是(b, c),而不是b或c。
4.2 表头、表尾的递归拆解技巧
软考对广义表的考查,最经典的一类题是“已知广义表,求连续取表头或表尾后的结果”。这类题的目的不是考验记忆力,而是考验对递归定义的理解。要拆解这类题,我的经验是:每次只做一步操作,然后在草稿纸上把新的表写出来,再继续下一步。
比如广义表L = ((a, b), c, d),求Tail(Head(Tail(L)))。可以从最内层开始拆解:
Tail(L):L去掉第一个元素(a, b),剩下的是(c, d),所以Tail(L) = (c, d)。Head(Tail(L)):取(c, d)的表头,是c。Tail(Head(Tail(L))):取c的表尾。注意,c是原子,原子的表尾是空表(),因为广义表的定义中,原子可以看作退化的广义表,它的表尾为空。
所以结果是()。
这里有个易错点:原子也能取表尾吗?严格来说,广义表的表头、表尾操作要求操作对象是广义表。但在软考的题目中,原子常被视为一个仅含该原子的广义表,所以其表尾是空表。这一点要注意。当然,如果题目没有明确说原子不能取表尾,默认按广义表规则处理。
4.3 广义表的长度与深度计算
长度是广义表中元素的个数,这里“元素”指的是直接元素,不递归展开。比如(a, (b, c), d)的长度是3,因为直接元素是a、(b, c)、d三个。深度则是括号嵌套的最大层数,空表深度为1,原子深度为0。比如(a, (b, (c)))的深度是3。
深度计算的递归定义是:Depth(A) = 1 + max(Depth(x)),其中x是A的所有直接元素。特殊地,原子的深度为0,空表(即())的深度为1。我建议遇到深度计算题时,先画出括号嵌套的层级,然后从最内层往外逐层加1,这样不容易出错。
软考偶尔会把广义表和二叉树、图的遍历结合起来考。比如让你判断一个广义表和某棵树的结构是否一致,或者用广义表表示一棵二叉树。二叉树可以表示为(根节点,左子树,右子树),其中左子树和右子树本身又是广义表。这种题的关键是分清“节点”和“子树”,不要混淆。
4.4 广义表存储结构的理解要点
广义表可以采用两种存储结构:头尾链表存储结构和扩展线性链表存储结构。软考对存储结构的考查停留在概念层面,通常不会让你手写完整代码,但会考这两种结构的节点类型和图解识别。
头尾链表存储结构中,每个表节点包含两个指针:表头指针和表尾指针。表头指针指向该表的第一个元素,表尾指针指向除去第一个元素后剩余元素组成的表。如果元素是原子,则用原子节点存储,原子节点中有一个标志位区分原子和子表,同时存储数据值。
扩展线性链表存储结构中,每个节点也包含两个指针:第一个指针指向该表的第一个元素,第二个指针指向该表的下一个兄弟元素。这种结构更像是把树转换成二叉树的过程,每个表看成一棵树,第一个元素是“长子”,第二个指针指向“下一个兄弟”。
在考试中,如果能识别出这两种结构的差异,选择题基本就能拿分。如果遇到画图题,优先按“头尾链表结构”画,因为它在教材中出现的频率更高。
提示:广义表的内容看起来抽象,但考试题型非常固定。我建议集中刷最近5年的选择题,把每一道广义表题归纳为“求表头表尾”“求长度深度”“判断存储结构”三类,你会发现出题套路几乎没有变化。
5. 软考真题高频题型:从概念到计算的全拆解
5.1 选择题常考的4类题型与速解模板
结合历年真题,多维数据结构部分的选择题基本逃不出下面这4类。我把每一类的出题特点和速解思路整理成了模板,临考前直接背模板比临时推导要稳妥得多。
第一类:数组地址计算题。核心思路是“要素定位法”。先在草稿纸上写下五个要素——数组维度、各维范围(下标从几到几)、存储方式(行优先还是列优先)、每个元素占用单元数L、数组首地址。然后根据元素下标,计算偏移量,再乘以L,加上首地址。遇到反推下标的题,用“偏移量除列数或行数”的方法。
第二类:矩阵压缩映射题。核心思路是“先判断矩阵类型,再套对应的映射公式”。对称矩阵和三角矩阵的难点在于公式记忆,我建议不要死记硬背,而是理解“前i-1行元素总数 + 当前行内的偏移”这个推导逻辑。考试时如果一时想不起公式,可以用小矩阵(比如3×3)现场推一遍,熟练后不到一分钟就能推出来。
第三类:广义表计算题。核心思路是“一步一化简”。表头表尾的操作,每次只做一步,写出中间结果再继续。长度只看直接元素个数,深度看括号层数。遇到混合运算,从最内层括号开始拆。
第四类:稀疏矩阵与三元组表题。核心思路是“按行优先顺序扫描矩阵,逐行收集非零元素”。转置题用“统计-定位-填充”三步法,不要硬转置。
5.2 下午题中数据结构的低频出现与应对策略
软件设计师下午题(案例分析题)通常包含数据流图、数据库设计、UML建模、算法设计和C语言编程等题目,多维数据结构很少作为独立大题出现,但它的身影会悄悄藏在算法设计题中。
最典型的是算法设计题中会要求你实现“矩阵相加”“矩阵转置”“稀疏矩阵乘法”之类的操作。这类题目如果考到稀疏矩阵,往往需要你定义三元组结构体,并实现转置或乘法算法。虽然近几年下午题更偏重排序、查找和图算法,但多维数据结构的底子不好,遇到矩阵题就会特别吃力。
我的建议是,把数组、矩阵压缩、广义表的代码实现能力作为“备而不用”的储备。重点掌握两个代码模板:三元组表的快速转置算法和对称矩阵的压缩存储赋值与读取。这两个代码量都不大,逻辑清晰,万一考到就是送分题。
5.3 易错题型专项:下标互推与连续的Tail操作
下标互推是选择题中错误率最高的一类。比如,按行优先存储的对称矩阵A[1..6][1..6],只存储下三角,问A[4][2]存储在一维数组的第几个位置(假设一维数组下标从1开始)。
解法:因为存储下三角,且i=4 ≥ j=2,根据公式k = i(i-1)/2 + j = 4*3/2 + 2 = 8。这里的8就是在一维数组中的位置(从1开始)。如果你用从0开始的公式,会算出7,和正确答案差1。
连续的Tail操作,是另一个高频失分点。比如广义表L = ((a, b, c), d, (e, f)),求Tail(Tail(L))。
Tail(L) = (d, (e, f))Tail(Tail(L)) = ((e, f))
注意,((e, f))是一个表,它的唯一元素是子表(e, f)。所以Tail(Tail(L))和(e, f)是不同的。前者是一个“外层还有一个括号”的表,后者是子表本身。有些考题会故意在这里设陷阱,问你两者的区别,或者继续做Head操作。如果题目问Head(Tail(Tail(L))),结果是(e, f),而不是e。
5.4 近5年真题考点频率分析
我统计了近5年(2019-2023)软考软件设计师真题中多维数据结构相关题目的分布,大致频率如下:
| 考点 | 出现频率 | 典型出题形式 |
|---|---|---|
| 二维数组地址计算 | 每年1-2题 | 行优先/列优先,求地址或反推下标 |
| 对称矩阵/三角矩阵压缩 | 每1-2年1题 | 求一维下标,求存储总长 |
| 稀疏矩阵三元组 | 每2年1题 | 三元组表转置,还原矩阵 |
| 广义表表头表尾 | 每年1题 | 连续取表头/表尾,求结果 |
| 广义表长度/深度 | 每1-2年1题 | 直接计算或结合存储结构 |
| 十字链表概念 | 近年较少 | 结构识别、与三元组对比 |
从频率来看,数组地址计算和广义表是绝对的重点,每年基本都能遇到。矩阵压缩的考频略低,但一旦出现,分值通常是2分,而且因为公式繁多,容易被拉开差距。
6. 临考冲刺:高频考点速记与错误避坑指南
6.1 考前必背公式速查表
临考前几天,不建议再去翻教材推导公式,而应该把高频公式浓缩在一张纸上,每天过一遍。下面这张速查表是我自己整理的重点,按考题出现频率排序。
| 内容 | 公式或结论 | 使用条件 |
|---|---|---|
| 一维数组地址 | LOC(ai) = LOC(a0) + i × L | 下标从0开始 |
| 二维数组行优先地址 | LOC(A[i][j]) = LOC(A[0][0]) + (i × n + j) × L | 下标从0开始,n为列数 |
| 二维数组列优先地址 | LOC(A[i][j]) = LOC(A[0][0]) + (j × m + i) × L | 下标从0开始,m为行数 |
| 对称矩阵下三角下标 | k = i(i+1)/2 + j | 下标从0开始,i ≥ j |
| 下三角矩阵存储总长 | n(n+1)/2 + 1 | 含常数c |
| 上三角矩阵下标 | k = i(2n - i + 1)/2 + (j - i) | 下标从0开始,i ≤ j |
| 广义表长度 | 直接元素个数 | 不递归展开 |
| 广义表深度 | 1 + max(子表深度) | 原子深度为0,空表深度为1 |
| 广义表表头 | 第一个元素 | 可能是原子或子表 |
| 广义表表尾 | 除第一个元素外其余元素组成的表 | 一定是表,不是原子 |
这张表不用死记,而是要能“推”。前面已经讲了怎么推导,考场上一旦卡壳,用一个3×3的小矩阵快速验算即可。
6.2 多选题与概念题的命题陷阱
软考上午题虽然以单选为主,但概念题中会出现“以下说法正确的是”“以下错误的是”这类变相多选题,干扰项设置非常刁钻。针对多维数据结构,常见的陷阱说法有:
陷阱一:“对称矩阵只需要存储下三角元素。”这种说法不严谨,应该说“只需存储上三角或下三角其一”,因为从另一个三角可以通过对称性推出来。
陷阱二:“广义表的深度等于长度。”这完全是两个概念,长度是元素个数,深度是嵌套层数,没有任何必然关系。比如((a), (b), (c))长度为3,深度为2。
陷阱三:“三元组表能直接进行矩阵加减法运算。”三元组表存储的是稀疏矩阵的非零元素,如果两个矩阵的非零元素位置不一致,直接运算会非常麻烦,通常需要先还原成二维数组,或者进行特殊处理。所以这个说法是错的。
陷阱四:“数组是一种非线性结构。”数组在逻辑上是线性结构,因为元素之间存在唯一的前驱和后继关系。多维数组从存储角度看是线性的,从逻辑上看是多维的,但软考通常将数组归为线性结构。因此,看到“数组是非线性结构”必须果断排除。
陷阱五:“广义表中不能包含自身。”这其实是递归定义造成的误解。广义表可以递归定义,某些广义表在概念上可以引用自身,比如A = (a, A)。虽然这种表在计算机存储中实现比较复杂,但在理论定义上是允许的。软考如果考这个概念,通常是以判断题形式出现。
6.3 三个最容易在考场上犯的低级错误
经验之谈,简化成三个字:漏、转、混。
漏,是指漏掉题目开头那句不起眼的条件,比如“假设数组下标从1开始”,或者在矩阵压缩题里漏看“矩阵从1开始编号”,导致整个公式用错。解决方法是,做题前把题干的数字条件圈出来,特别是起点、步长、边界值。
转,是指转置矩阵时忘了重新排序。三元组表转置后,行号列号虽然交换了,但顺序不会自动变成“按行优先”,需要重新按新行号排序。有些题直接问“转置后的三元组表是什么”,如果你没有排序,答案就错了。
混,是指混淆行优先和列优先。软考为了增加区分度,有时会在同一个题目里同时出现“数组A按行优先存储”“矩阵B按列优先存储”,如果你在计算时没有区分开,后面就全乱了。
6.4 刷题路径与复习节奏建议
如果你距离考试还有三到四周,我建议按下面的节奏推进多维数据结构部分:
第一周:用两天时间把数组地址计算全部类型刷一遍,包括一维、二维、下标从1开始、列优先、反推下标。重点理解“偏移量”的概念,而不是死背公式。再用两天时间攻克矩阵压缩,把对称矩阵、三角矩阵的推导过程亲自做一遍,然后刷真题。
第二周:用两天时间刷广义表的表头表尾和长度深度题,把近五年的真题全部做一遍,总结出题套路。后面几天开始做套题,遇到多维数据结构的题就重点标记,整理错题本。
第三周及以后:每天花10分钟过一遍速查表,然后从近三年真题中随机抽取多维数据结构相关题目练手,保持手感。如果时间紧张,优先保证数组地址计算和广义表题目,因为这两类题最稳定、最容易拿分。
我个人在备考时有个习惯:把每一道错题都抄在一个小本子上,并标注错误原因(公式用错、漏看条件、计算粗心等)。考前三天翻一遍错题本,效果比做十套新题都好。因为错题本记录的正是你的思维盲区,而新题很难精准命中这些盲区。
7. 实操心得:我用“小矩阵反推法”解决公式遗忘问题
最后分享一个实战技巧。很多考生担心考场上公式记不住,我自己的应对办法是“小矩阵反推法”——不管遇到什么矩阵压缩题,先写一个3×3的小矩阵,用最笨的方式把存储序列列出来,然后反推公式。
举个例子,记不清上三角矩阵的映射公式时,我就写一个3×3的上三角矩阵:
1 2 3 0 4 5 0 0 6按行优先存储,存储序列是1 2 3 4 5 6,对应位置关系是:A[0][0] → 0,A[0][1] → 1,A[0][2] → 2,A[1][1] → 3,A[1][2] → 4,A[2][2] → 5。然后我用A[1][2]来验证公式:k = i(2n - i + 1)/2 + (j - i) = 1 * (6 - 1 + 1)/2 + (2 - 1) = 1 * 6 / 2 + 1 = 3 + 1 = 4,结果和手动序列吻合,说明公式正确。
这个方法在考场上特别实用。因为3×3矩阵的存储序列不超过6个元素,手动列出来只需要十几秒钟,但能帮你确认公式是否正确,避免因为记忆偏差导致整题全错。
多维数据结构在软考中占的分值并不算最多,但它性价比很高。只要理解了底层逻辑、掌握了公式推导方法、刷透近五年真题,这部分分数基本是必拿的。不要在这些基础题上丢分,你的上午题总分就会更有保障。