Appearance
特殊矩阵的压缩存储
前置:多维数组的存储。本篇所有压缩公式都建立在那里的"行优先 / 列优先地址公式"地基上——压缩存储的本质就是"砍掉冗余位置"后重新数地址。
一、为什么要压缩
对于
对称矩阵:朴素要 个单元,但有用信息只有上三角 个——浪费一半 三对角矩阵:朴素要 个单元,但非零的只有 个——浪费 99.7% 稀疏矩阵(非零元素 100 个):朴素要 个单元,浪费 99.99%
压缩存储的目标:只保留有用信息,并能
四类特殊矩阵的压缩思路:
| 矩阵 | 规律 | 压缩思路 |
|---|---|---|
| 对称矩阵 | 只存一半三角 | |
| 三角矩阵 | 一半三角全是常数 | 存非零三角 + 1 个 |
| 三对角矩阵 | 非零只在 | 只存三条带 |
| 稀疏矩阵 | 非零元素稀疏分布、无规律 | 存 (行, 列, 值) 三元组 |
前三类是规律性压缩(位置可由
二、对称矩阵
2.1 定义
2.2 存储策略
只存上三角(包含对角线,
下面以"只存上三角"为例(408 考研最常考的形态),分别推导行优先和列优先的下标公式。
2.3 上三角 · 行优先公式(1-based)
第
text
i=1 : m11 m12 m13 ... m1n (n 个)
i=2 : m22 m23 ... m2n (n-1 个)
i=3 : m33 ... m3n (n-2 个)
...
i=n : mnn (1 个)- 前
行共有 个元素 - 第
行内 之前还有 个元素
0-based 下标(一维数组从
2.4 真题精讲:2018-03(上三角行优先)
设有一个
的对称矩阵 ,将其上三角部分的元素 按行优先存入 C 语言的一维数组 中,元素 在 中的下标是?
第一步:
第二步:代入公式
手算验证:前 5 行的元素数
2.5 上三角 · 列优先公式(1-based)
把行/列角色对调。第
text
j=1 : m11 (1 个)
j=2 : m12 m22 (2 个)
j=3 : m13 m23 m33 (3 个)
...
j=n : m1n m2n m3n ... mnn (n 个)注意写法上:第
- 前
列共有 个元素 - 第
列内 之前还有 个元素
0-based 下标:
2.6 真题精讲:2020-01(上三角列优先 + 对称性)
将一个
对称矩阵 的上三角部分的元素 ( ),按列优先存入 C 语言的一维数组 中,元素 在 中的下标是?
第一步:用对称性把元素挪到上三角。
题目说"只存
实际查
第二步:代入列优先公式
答案 22。
编者注(对称矩阵下三角元素的查询模板):题目"只存了上三角"+ 你要查的元素在下三角时,三步走:① 用
交换下标;② 重新核对交换后是否进入上三角( );③ 代入公式。漏掉第一步是 2020-01 选错最常见的原因。
2.7 行优先 vs 列优先:什么时候用哪个公式
题面会明确写出"按行优先" / "按列优先"。两种公式的关键区别:
| 行优先 | 列优先 | |
|---|---|---|
| 第 | ||
| "前部"求和 | ||
| 行内偏移 |
编者注(对称记忆):行优先和列优先看似"两套公式",本质是一回事——同一个三角形按两种顺序遍历的不同计数方式。考场上不要硬背两个公式——理解了"前
行/列总长 + 当前行/列偏移"的拆分逻辑,公式现场推就行。
三、三角矩阵
3.1 定义
上三角矩阵:所有
text
* * * *
0 * * * ← 下三角全是常数 c(这里 c=0)
0 0 * *
0 0 0 *下三角矩阵:所有
3.2 压缩策略
- 存所有
的元素(上三角的非常数部分),共 个 - 再额外存 1 个常数
总空间:
3.3 下标公式
上三角矩阵:非常数部分(
常数
下三角矩阵:非常数部分(
编者注(三角矩阵 vs 对称矩阵):两个考点常常被混淆。对称矩阵存"一半三角"是因为另一半重复,两半内容相同;三角矩阵存"一半三角"是因为另一半全是常数,两半内容不同(一半有值、另一半是
)。考试题里有时会刻意省略这个区分,需要从题面"对称 / 三角 / 主对角线"几个关键词判定。
四、三对角矩阵
4.1 定义
只有满足
text
n=5 时的非零分布:
* *
* * *
* * *
* * *
* *4.2 每行非零元素数
- 第
行: —— 2 个 - 第
行: —— 3 个 - 第
行: —— 2 个
总非零数:
4.3 行优先下标公式(1-based)
设
第
0-based 下标(
边界行(
4.4 真题精讲:2016-04
有一个 100 阶的三对角矩阵
,其元素 按行优先依次压缩存入下标从 0 开始的一维数组 中。元素 在数组 中的下标是?
代入
手算验证:第 30 行之前共有
答案 87。
4.5 三对角矩阵的三个高频坑
- 第 1 行只有 2 个元素——把所有行都按 3 个算,前缀和会算错(
vs 正确的 ) - "主对角线
" vs "上副对角线 " 混淆—— 在第 30 行的中间(位置 1),不是第一个(位置 0) - 公式
只对中间行成立—— 或 时单独处理
五、稀疏矩阵
5.1 定义
非零元素个数
没有正式的"稀疏度阈值"——一般认为
5.2 三元组表
最简单的稀疏存储:对每个非零元素
辅助信息:
c
typedef struct {
int rows; // M 的行数
int cols; // M 的列数
int nums; // 非零元素个数
Triple data[N]; // 三元组数组
} TSMatrix;5.3 真题精讲:2023-03(三元组必须存什么)
若采用三元组表存储结构存储稀疏矩阵 M,则除三元组外,下列数据中还需要保存的是?
I. M 的行数 II. M 中包含非零元素的行数 III. M 的列数 IV. M 中包含非零元素的列数
正确答案 I 和 III——存矩阵的原始行数和列数。
为什么 II 和 IV 不行?
反例:考虑一个
text
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0- 三元组:
- 非零行数 II = 1,非零列数 IV = 1
- 如果只存 II + IV,重建出来的矩阵是
,原矩阵的 4 行 4 列零元素信息全部丢失
所以必须存"原始行列数"(I + III),而不是"非零行列数"(II + IV)。
编者注(三元组的设计原则):辅助信息要做到 ① 能完整恢复原矩阵形状;② 能完整恢复非零元素。三元组本身负责非零元素,行列数负责形状——两者合起来无冗余、无缺失。多存(D 选项)增加冗余,少存或换错存(B/C 选项)信息不够。
5.4 真题精讲:2017-03(稀疏矩阵的存储结构辨析)
适用于压缩存储稀疏矩阵的两种存储结构是?
A. 三元组表和十字链表 B. 三元组表和邻接矩阵 C. 十字链表和二叉链表 D. 邻接矩阵和十字链表
正确答案 A。
关键辨析:
| 结构 | 是否压缩稀疏矩阵 | 真实用途 |
|---|---|---|
| 三元组表 | ✓ | 稀疏矩阵专用 |
| 十字链表 | ✓ | 稀疏矩阵专用(行/列双向遍历) |
| 邻接矩阵 | ✗ | 图的稠密存储, |
| 二叉链表 | ✗ | 二叉树节点的 lchild / rchild 链接结构 |
编者注(邻接矩阵的命名陷阱):邻接矩阵的"矩阵"二字容易让人以为它"和稀疏矩阵相关"。实际上它就是一个普通的
二维数组(行列下标对应顶点编号,元素表示边权或邻接关系),完全不压缩,0 元素照常占内存。它自己是稀疏矩阵存储要解决的问题之一——稀疏图的邻接矩阵用三元组或十字链表压缩才高效。
5.5 十字链表
适合频繁修改的稀疏矩阵(增删非零元素)。每个非零元素是一个节点:
c
typedef struct OLNode {
int row, col; // 行、列号
ElemType value; // 元素值
struct OLNode *right; // 同一行内下一个非零元素
struct OLNode *down; // 同一列内下一个非零元素
} OLNode;每个节点同时挂在所在行链表和列链表两个链表上——所以叫"十字"。一个
优势:
- 行方向遍历某行所有非零元素:沿
right走一遍, - 列方向遍历某列所有非零元素:沿
down走一遍, - 插入新非零元素:找到行链表和列链表中的位置后插入,
,不需要移动其它元素
劣势:每个节点带 4 个域(2 个指针 + 行号 + 列号 + 值),单元素开销比三元组大。
5.6 三元组 vs 十字链表
| 三元组表 | 十字链表 | |
|---|---|---|
| 存储开销(单个非零元素) | 小( | 大(再多 2 个指针) |
| 插入 / 删除 | 慢(数组要移位) | 快(链表 |
| 矩阵加法 / 转置 | 中等 | 较慢但代码清晰 |
| 适用场景 | 静态稀疏矩阵 | 频繁修改 |
408 选择题里两者各有出现,但三元组表的出题频率明显更高。十字链表在题里多半作为"另一个正确选项"出现(如 2017-03)。
六、四类矩阵对比速查表
| 矩阵 | 非零分布 | 压缩后大小 | 关键公式(0-based 行优先) |
|---|---|---|---|
| 对称矩阵(上三角) | |||
| 对称矩阵(上三角,列优先) | |||
| 三角矩阵 | 一半 + 1 个常数 | 同对称矩阵的对应三角 | |
| 三对角矩阵 | |||
| 稀疏矩阵(三元组) | 任意稀疏 | 显式存 | |
| 稀疏矩阵(十字链表) | 任意稀疏 | 链表节点,无下标公式 |
七、交互可视化:四种矩阵综合演练
打开下方可视化:顶部切换「对称 / 三角 / 三对角 / 稀疏」四种矩阵,点击网格任意元素查看下标推导。带「真题预设」按钮一键加载 2018-03 / 2020-01 / 2016-04 / 2023-03 四道题的初始配置,直接看 ds-visual 跑出正确答案的过程。
八、考点速记(考前 30 秒过)
- 对称矩阵:用对称性
把元素挪到被存的三角;推公式的两件套是"前几行/列累加 + 行/列内偏移" - 三角矩阵:和对称矩阵的下标公式完全一样,只是末尾多存 1 个常数
- 三对角矩阵:中间行公式
,第 1 行只有 2 个元素是边界陷阱 - 稀疏矩阵三元组:除了三元组本身,还要存"原矩阵的行数和列数"(不是非零行列数)
- 邻接矩阵不是稀疏矩阵的压缩结构——它是图的稠密存储,看到"矩阵"二字别误判
- base 看清:题面 1-based 和 C 数组 0-based 的转换在最后一步做
九、本章真题清单
codebrick 题库中考查 matrix-storage 或 special-matrix 知识点的真题:
| 年份 | 题号 | 考点 | 难度 |
|---|---|---|---|
| 2016 | 04 | 三对角矩阵 + 行优先下标 | ★★★ |
| 2017 | 03 | 稀疏矩阵存储结构辨析(三元组 vs 邻接矩阵) | ★★ |
| 2018 | 03 | 对称矩阵 + 上三角行优先下标 | ★★★ |
| 2020 | 01 | 对称矩阵 + 上三角列优先 + 对称性 | ★★★ |
| 2021 | 03 | 二维数组 + 行优先地址 + 反推 n | ★★ |
| 2023 | 03 | 稀疏矩阵三元组 + 必存辅助信息 | ★★ |
近 10 年 6 次出现,平均 1.7 年 / 次。最近一次 2023 年,2024 和 2025 未考——按命题轨迹规律是中频考点的标准沉寂期,2026 备考需要重点掌握。
编者注(学完之后该做什么):这一章公式多、易错点密。建议做法:① 把对称矩阵两个公式(行/列优先)至少各推导一遍,不要硬背;② 把上面 6 道真题在 codebrick 题库 (
/practice/browse/ds) 顺序刷一遍,每道题做完看错因;③ 三对角矩阵和三角矩阵的下标公式可以放在最后,因为它们和对称矩阵共享同一套推导思路。