矩阵基础

从数学定义到程序实现

矩阵的定义与表示

矩阵(Matrix)是由 m×n 个数 \(a_{ij}\) 排成的 m 行(row)n 列(column)的数表,通常用大写字母 A、B 等表示。其中 \(a_{ij}\) 表示位于第 i 行、第 j 列的元素。

A = [aij]m×n = ( a11 a12 a1n a21 a22 a2n am1 am2 amn )

在计算机程序中,矩阵通常使用二维数组(或类似结构,如 C++ 中的 `vector>`)来表示。例如,一个 4x4 的矩阵可以这样可视化:

矩阵加法与数乘

矩阵加法:只有当两个矩阵 A 和 B 的行数和列数都相同时(称为同型矩阵),它们才能相加。和矩阵 C = A + B 的每个元素等于 A 和 B 对应元素的和。

(A + B)ij = Aij + Bij

矩阵数乘:用一个标量(普通的数)k 乘以矩阵 A,结果是 A 中的每个元素都乘以 k。

(k · A)ij = k · Aij

矩阵 A

矩阵 B

结果矩阵 C

矩阵转置

矩阵的转置(Transpose)操作是将原矩阵 A 的行与列互换得到的新矩阵,记作 AT 或 A'。如果 A 是一个 m×n 矩阵,则其转置 AT 是一个 n×m 矩阵。

(AT)ij = Aji

简单来说,原矩阵的第 i 行变成了转置矩阵的第 i 列,原矩阵的第 j 列变成了转置矩阵的第 j 行。

原矩阵 A

转置矩阵 AT

3行 4列 的转置是 4行 3列

矩阵遍历

遍历矩阵是指按照特定的顺序访问(读取或处理)矩阵中的每一个元素。最常见的两种遍历方式是行优先遍历和列优先遍历。

行优先遍历(Row-Major Order):这是最自然的方式,如同阅读文本一样。先访问完第一行的所有元素(从左到右),然后访问第二行的所有元素,以此类推,直到最后一行。

列优先遍历(Column-Major Order):先访问完第一列的所有元素(从上到下),然后访问第二列的所有元素,以此类推,直到最后一列。某些语言(如Fortran, MATLAB, R)默认按列存储数据,这种遍历方式在这些环境中更高效。

示例矩阵

遍历顺序将显示在这里...

矩阵查找

在矩阵中查找一个特定值的元素是常见操作。根据矩阵的特性,查找策略也不同。

暴力查找(Brute-Force Search):适用于任何普通矩阵。方法很简单:逐个检查矩阵中的每个元素,看它是否等于目标值。如果找到了,返回成功(通常还带上位置信息);如果遍历完所有元素都没找到,返回失败。

时间复杂度:O(m × n)

优化查找(适用于特定有序矩阵):如果一个矩阵满足特殊条件:每一行从左到右递增,每一列从上到下递增,那么我们可以使用一种更高效的查找方法。

思路:从矩阵的 右上角(或左下角)元素开始比较。设当前元素为 \(A_{ij}\):

  • 如果 \(A_{ij}\) 等于目标值,查找成功。
  • 如果 \(A_{ij}\) 大于目标值,说明目标值不可能在当前列(因为列是递增的),所以向左移动一列(j--)。
  • 如果 \(A_{ij}\) 小于目标值,说明目标值不可能在当前行(因为行是递增的),所以向下移动一行(i++)。

重复此过程,直到找到目标值或超出矩阵边界(查找失败)。

时间复杂度:O(m + n)

查找矩阵

查找过程和结果将显示在这里...

练习题与知识延伸

选择题测试

1. 进行矩阵加法运算时,两个矩阵必须满足什么条件?
A. 可以是任意形状
B. 行数必须相同
C. 列数必须相同
D. 行数和列数都必须相同(同型矩阵)

编程练习 (思路与参考实现)

练习 1: 实现一个 C++ 函数,计算两个给定 3x3 矩阵的和,并返回结果矩阵。
练习 2: 实现一个 C++ 函数,在一个行列均升序的 m x n 矩阵中查找目标值 target,找到返回 true,否则返回 false,要求时间复杂度为 O(m+n)。

知识延伸

矩阵分块遍历(Block Matrix Traversal)

对于非常大的矩阵,直接按行或按列遍历可能导致缓存未命中(Cache Miss)增多,影响性能。将大矩阵逻辑上划分为若干个小的子矩阵(块),优先处理完一个块内的所有数据,可以更好地利用 CPU 缓存的局部性原理,提高计算密集型操作(如矩阵乘法)的速度。

二维前缀和与差分数组

二维前缀和:预计算一个"和矩阵" S,其中 S[i][j] 表示原矩阵左上角到 (i, j) 位置构成的子矩阵的元素之和。这样,任意子矩阵 (x1, y1) 到 (x2, y2) 的元素和可以在 O(1) 时间内通过 S[x2][y2] - S[x1-1][y2] - S[x2][y1-1] + S[x1-1][y1-1] 计算得出。

二维差分数组:用于快速处理对矩阵某个子区域进行统一增减值的操作。通过在一个"差分矩阵" D 的四个关键点进行修改(O(1) 操作),可以实现对原矩阵一个矩形区域内所有元素加 k 的效果。查询原矩阵某个元素的值时,需要计算其对应差分矩阵的前缀和(O(n*m) 恢复)。

稀疏矩阵(Sparse Matrix)的存储与优化

当矩阵中绝大多数元素为零时,称为稀疏矩阵。使用标准的二维数组存储会浪费大量空间。可以采用压缩存储方法,只记录非零元素的值及其行列索引。常见的格式有:

  • COO (Coordinate list):用三个数组分别存储非零元素的值、行索引、列索引。
  • CSR (Compressed Sparse Row):更常用,对行进行压缩。使用三个数组:一个存所有非零元素的值(按行优先顺序),一个存对应列索引,一个存每行第一个非零元素在值数组中的起始位置。
  • CSC (Compressed Sparse Column):与 CSR 类似,按列压缩。

基于这些压缩格式,矩阵运算(如乘法、查找)也需要实现特定算法以保持效率。