Skip to content

408

数据结构

DS-03-03 多维数组的存储(行优先/列优先)


一、定位信息

项目内容
所属圈层核心层
考点热度M级(中频常考) — 数组存储地址计算在408选择题中偶有出现,通常2分,主要考查行优先/列优先地址公式的应用
前置知识回顾需理解"数组"的基本概念(连续存储的线性表),以及基本的地址计算原理(每个元素占 sizeof(元素类型)\text{sizeof(元素类型)} 个字节)
知识网络定位多维数组的存储方式是特殊矩阵压缩存储的基础,理解行优先/列优先的地址映射才能掌握后续的压缩存储下标计算

二、知识点讲解

2.1 数组的定义

数组(Array) 是由相同类型的数据元素构成的有限序列,每个元素通过下标唯一标识。

  • 一维数组:线性结构,元素按下标线性排列
  • 二维数组:可视为"数组的数组",即每个元素本身是一个一维数组
  • nn 维数组:递归定义

直观理解:二维数组就是一个表格(矩阵),有行有列。例如 A3×4A_{3 \times 4} 是一个3行4列的矩阵,元素 aija_{ij} 位于第 ii 行第 jj 列。

Am×n=(a00a01a0,n1a10a11a1,n1am1,0am1,1am1,n1)A_{m \times n} = \begin{pmatrix} a_{00} & a_{01} & \cdots & a_{0,n-1} \\ a_{10} & a_{11} & \cdots & a_{1,n-1} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m-1,0} & a_{m-1,1} & \cdots & a_{m-1,n-1} \end{pmatrix}

2.2 行优先存储(Row-Major Order)

行优先:将二维数组的元素按行依次存入连续内存。先存第0行,再存第1行,依此类推。

存储顺序:a00,a01,,a0,n1,a10,a11,,a1,n1,a_{00}, a_{01}, \ldots, a_{0,n-1}, a_{10}, a_{11}, \ldots, a_{1,n-1}, \ldots

地址公式(下标从0开始,首地址为 LOC(a00)\text{LOC}(a_{00})):

LOC(aij)=LOC(a00)+(i×n+j)×L\text{LOC}(a_{ij}) = \text{LOC}(a_{00}) + (i \times n + j) \times L

其中 nn 为列数,LL 为每个元素占用的字节数。

推导:元素 aija_{ij} 前面有 ii 行完整的元素(每行 nn 个),加上当前行中 jj 个元素,共 (i×n+j)(i \times n + j) 个元素,每个占 LL 字节。

示例A3×4A_{3 \times 4}(3行4列),L=4L=4 字节,首地址为 100。

  • LOC(a00)=100\text{LOC}(a_{00}) = 100
  • LOC(a03)=100+(0×4+3)×4=112\text{LOC}(a_{03}) = 100 + (0 \times 4 + 3) \times 4 = 112
  • LOC(a10)=100+(1×4+0)×4=116\text{LOC}(a_{10}) = 100 + (1 \times 4 + 0) \times 4 = 116
  • LOC(a23)=100+(2×4+3)×4=144\text{LOC}(a_{23}) = 100 + (2 \times 4 + 3) \times 4 = 144

2.3 列优先存储(Column-Major Order)

列优先:将二维数组的元素按列依次存入连续内存。先存第0列,再存第1列,依此类推。

存储顺序:a00,a10,,am1,0,a01,a11,,am1,1,a_{00}, a_{10}, \ldots, a_{m-1,0}, a_{01}, a_{11}, \ldots, a_{m-1,1}, \ldots

地址公式(下标从0开始):

LOC(aij)=LOC(a00)+(j×m+i)×L\text{LOC}(a_{ij}) = \text{LOC}(a_{00}) + (j \times m + i) \times L

其中 mm 为行数,LL 为每个元素占用的字节数。

推导:元素 aija_{ij} 前面有 jj 列完整的元素(每列 mm 个),加上当前列中 ii 个元素,共 (j×m+i)(j \times m + i) 个元素。

2.4 下标从1开始的地址公式

若数组下标从1开始(即 A[1..m][1..n]A[1..m][1..n]),则:

  • 行优先LOC(aij)=LOC(a11)+[(i1)×n+(j1)]×L\text{LOC}(a_{ij}) = \text{LOC}(a_{11}) + [(i-1) \times n + (j-1)] \times L
  • 列优先LOC(aij)=LOC(a11)+[(j1)×m+(i1)]×L\text{LOC}(a_{ij}) = \text{LOC}(a_{11}) + [(j-1) \times m + (i-1)] \times L

408考试注意:审题时一定要确认下标是从0还是从1开始,选用对应公式!

2.5 nn 维数组的地址计算

nn 维数组 A[d1][d2][dn]A[d_1][d_2] \cdots [d_n],每维大小为 d1,d2,,dnd_1, d_2, \ldots, d_n,元素 ai1i2ina_{i_1 i_2 \cdots i_n}

行优先(即最后一维变化最快)地址公式:

LOC(ai1i2in)=LOC(a00)+(k=1n1ikt=k+1ndt+in)×L\text{LOC}(a_{i_1 i_2 \cdots i_n}) = \text{LOC}(a_{0 \cdots 0}) + \left(\sum_{k=1}^{n-1} i_k \prod_{t=k+1}^{n} d_t + i_n\right) \times L

此公式在408中很少直接考查高维情况,但理解其推导逻辑有助于应对变式题。


三、记忆与理解辅助

技巧1:行优先/列优先口诀

"行优先——行不变列先变,列优先——列不变行先变"

或者:

"行优先按行排,一行存完存下一行;列优先按列排,一列存完存下一列"

技巧2:行优先 vs 列优先对比表

比较项行优先列优先
存储顺序先存完一行,再存下一行先存完一列,再存下一列
地址公式LOC(a00)+(i×n+j)×L\text{LOC}(a_{00}) + (i \times n + j) \times LLOC(a00)+(j×m+i)×L\text{LOC}(a_{00}) + (j \times m + i) \times L
快速访问按行遍历快(连续存储)按列遍历快(连续存储)
采用语言C/C++、Java、PythonFortran、MATLAB、R
408默认行优先(C语言风格)

技巧3:地址计算通用思路

无论行优先还是列优先,核心思路是:

  1. 数前面有多少个元素:按存储顺序,当前元素前面有多少个元素
  2. 乘以每个元素的字节数:得到偏移量
  3. 加上首地址:得到实际地址

地址=首地址+前面元素个数×L\text{地址} = \text{首地址} + \text{前面元素个数} \times L

技巧4:快速验证法

计算完地址后,用特殊位置验证:

  • a00a_{00}(或 a11a_{11})应该等于首地址
  • 相邻行同列元素的地址差应为 n×Ln \times L(行优先)或 LL(列优先)
  • 相邻列同行元素的地址差应为 LL(行优先)或 m×Lm \times L(列优先)

四、例题与精解

例题1(基础)

题目:已知二维数组 A[0..5][0..7]A[0..5][0..7](6行8列)按行优先存储,每个元素占4个字节,首地址为 200。求元素 A[3][5]A[3][5] 的存储地址。

命题意图:考查行优先地址公式的直接应用。

审题分析

  • 已知:下标从0开始,m=6m=6n=8n=8L=4L=4LOC(a00)=200\text{LOC}(a_{00})=200
  • 求解:LOC(a35)\text{LOC}(a_{35})

解题思路: 直接代入行优先地址公式。

完整步骤

LOC(a35)=LOC(a00)+(i×n+j)×L\text{LOC}(a_{35}) = \text{LOC}(a_{00}) + (i \times n + j) \times L=200+(3×8+5)×4= 200 + (3 \times 8 + 5) \times 4=200+29×4= 200 + 29 \times 4=200+116=316= 200 + 116 = 316

验证a35a_{35} 前面有 3×8+5=293 \times 8 + 5 = 29 个元素,每个4字节,偏移116字节,200+116=316200+116=316

方法反思:代入公式前先确认下标起始值和行列数,避免混淆 mmnn

例题2(中等)

题目:二维数组 A[1..10][1..20]A[1..10][1..20] 按列优先存储,首地址为 1000,每个元素占 8 字节。已知元素 A[i][j]A[i][j] 的地址为 1168,求 iijj 的值。

命题意图:考查列优先地址公式的逆向应用(已知地址求下标)。

审题分析

  • 已知:下标从1开始,m=10m=10n=20n=20L=8L=8LOC(a11)=1000\text{LOC}(a_{11})=1000LOC(aij)=1168\text{LOC}(a_{ij})=1168
  • 求解:iijj

解题思路: 列优先、下标从1开始的地址公式为: LOC(aij)=LOC(a11)+[(j1)×m+(i1)]×L\text{LOC}(a_{ij}) = \text{LOC}(a_{11}) + [(j-1) \times m + (i-1)] \times L

代入已知值,求解方程。

完整步骤

1168=1000+[(j1)×10+(i1)]×81168 = 1000 + [(j-1) \times 10 + (i-1)] \times 8168=[(j1)×10+(i1)]×8168 = [(j-1) \times 10 + (i-1)] \times 8(j1)×10+(i1)=168/8=21(j-1) \times 10 + (i-1) = 168 / 8 = 21

由于 1i101 \leq i \leq 10,所以 0i190 \leq i-1 \leq 9

(j1)×10+(i1)=21(j-1) \times 10 + (i-1) = 21,用除法分解:

  • 21÷10=2121 \div 10 = 2 \cdots 1
  • 所以 j1=2j-1=2i1=1i-1=1
  • j=3j=3i=2i=2

验证LOC(a23)=1000+[(31)×10+(21)]×8=1000+21×8=1000+168=1168\text{LOC}(a_{23}) = 1000 + [(3-1) \times 10 + (2-1)] \times 8 = 1000 + 21 \times 8 = 1000 + 168 = 1168

方法反思

  • 逆向求解的关键是带余除法:总元素序号除以每列元素数得到列偏移,余数为行偏移
  • 注意下标从1开始时公式中要减1
  • 此类题在408选择题中较常见,建议熟练掌握正向和逆向两个方向的计算

五、考情分析

分析维度内容
考查频次近5年出现1–2次(选择题为主),属于中低频考点
常见题型选择题(地址计算、已知地址求下标)
分值占比通常2分(选择题一道)
命题趋势单独出题较少,但作为矩阵压缩存储的基础,可能与压缩存储结合考查

:以上频次基于大纲权重与通用命题规律推测,待真题分析后校准。


六、易错点提醒

易错点1

  • 错误表现:行优先公式中把 mm(行数)和 nn(列数)搞反
  • 错误原因:行优先的关键是"一行有多少个元素"即列数 nn,但容易误用行数 mm
  • 正确做法:行优先公式中的系数是列数 nn(因为一行有 nn 个元素),列优先公式中的系数是行数 mm(因为一列有 mm 个元素)

易错点2

  • 错误表现:下标从1开始时忘记减1,直接套用下标从0的公式
  • 错误原因:考试中两种下标约定都可能出现,审题不仔细
  • 正确做法:看到下标从1开始,公式中必须将 ii 替换为 (i1)(i-1)jj 替换为 (j1)(j-1)

易错点3

  • 错误表现:列优先地址计算时,误将"前面元素个数"算成 (i×m+j)(i \times m + j) 而非 (j×m+i)(j \times m + i)
  • 错误原因:与行优先公式混淆
  • 正确做法:记住核心原则——"前面有多少个元素"。列优先时,先算前面有多少个完整列(jj 列,每列 mm 个),再加上当前列中 ii 个元素

易错点4

  • 错误表现:忽略每个元素占用的字节数 LL,直接把元素个数当地址偏移
  • 错误原因:忘记"地址偏移 = 元素个数 × 每个元素字节数"
  • 正确做法:始终区分"元素序号"和"字节偏移",最终地址 = 首地址 + 元素序号 × LL

七、来源标注

  • 依据2026考研统考大纲(408计算机学科专业基础综合)
  • 依据《数据结构(C语言版)》严蔚敏版
  • 依据《数据结构》王道考研辅导讲义

考研全科复习资料 - 基于2026考研统考大纲