从矩阵基础到代码实现:彻底理解广义矩阵乘法

从矩阵基础到代码实现:彻底理解广义矩阵乘法

作为编程新手,理解矩阵和矩阵乘法是学习许多算法和数据结构的基础。本文将从最基础的矩阵概念开始,逐步引导你理解一段 C++ 代码,该代码定义了一个矩阵结构体并实现了一种特殊的矩阵乘法 —— 广义矩阵乘积。通过本文的学习,你将不仅掌握矩阵的基本概念和运算规则,还能理解如何用 C++ 代码实现这些概念,并将其应用于解决实际问题。

一、矩阵的基本概念

1.1 什么是矩阵?

矩阵是数学中一种重要的数据结构,它由行(row)和列(column)组成,是一个二维的数值数组。简单来说,矩阵就是将数字按行和列排列成的矩形表格。例如:

\(A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix}\)

这是一个 2 行 3 列的矩阵,我们称它为 2×3 矩阵。矩阵中的每个数字称为矩阵的元素(element)或项(entry)。矩阵通常用大写字母表示,如 A、B、C 等,而矩阵中的元素则用对应的小写字母并加上行和列的索引来表示,如 aij表示矩阵 A 中第 i 行第 j 列的元素。

1.2 矩阵的基本术语

  • 维度(Dimension):矩阵的维度由它包含的行数和列数决定。一个 m 行 n 列的矩阵称为 m×n 矩阵。

  • 行矩阵(Row Matrix):只有一行的矩阵,例如 [1 2 3]。

  • 列矩阵(Column Matrix):只有一列的矩阵,例如:

\(\begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix}\)

  • 方阵(Square Matrix):行数和列数相等的矩阵,例如 3×3 矩阵。

  • 零矩阵(Zero Matrix):所有元素都为 0 的矩阵。

  • 单位矩阵(Identity Matrix):主对角线上的元素全为 1,其余元素全为 0 的方阵。例如 3×3 单位矩阵:

\(I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}\)

1.3 矩阵的运算

矩阵可以进行多种运算,包括加法、数乘和乘法等。这些运算都有特定的规则和条件:

  • 矩阵加法:两个矩阵必须具有相同的维度才能相加,结果矩阵的每个元素是原矩阵对应位置元素的和。

  • 数乘:一个标量(普通数字)与矩阵相乘,结果矩阵的每个元素是原矩阵对应元素与该标量的乘积。

  • 矩阵乘法:两个矩阵 A 和 B 可以相乘的条件是 A 的列数等于 B 的行数。结果矩阵 C 的每个元素 Cij等于 A 的第 i 行与 B 的第 j 列对应元素乘积的和。

二、矩阵乘法详解

2.1 矩阵乘法的基本规则

矩阵乘法是线性代数中的核心运算,也是理解本文代码的关键。让我们详细了解矩阵乘法的规则:

条件:矩阵 A(m×n)和矩阵 B(n×p)可以相乘,结果矩阵 C 是 m×p 的矩阵。

计算方式:结果矩阵 C 中的元素 Cij由以下公式计算:

\(C_{ij} = \sum_{k=1}^{n} A_{ik} \times B_{kj}\)

这表示 C 的第 i 行第 j 列元素是 A 的第 i 行与 B 的第 j 列对应元素相乘后相加的结果。

示例

假设有两个矩阵 A 和 B:

\(A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}, \quad B = \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}\)

它们的乘积 C = AB 计算如下:

\(C_{11} = 1×5 + 2×7 = 5 + 14 = 19 \\ C_{12} = 1×6 + 2×8 = 6 + 16 = 22 \\ C_{21} = 3×5 + 4×7 = 15 + 28 = 43 \\ C_{22} = 3×6 + 4×8 = 18 + 32 = 50 \\\)

结果矩阵 C 为:

\(C = \begin{bmatrix} 19 & 22 \\ 43 & 50 \end{bmatrix}\)

2.2 矩阵乘法的性质

矩阵乘法具有以下重要性质:

  1. 结合律:(AB)C = A(BC)

  2. 分配律:A(B + C) = AB + AC,(B + C)A = BA + CA

  3. 不满足交换律:一般情况下,AB ≠ BA

  4. 与单位矩阵相乘:AI = IA = A

2.3 广义矩阵乘法

本文代码实现的是一种特殊的矩阵乘法,称为广义矩阵乘法。与标准矩阵乘法不同,广义矩阵乘法使用不同的二元运算符来替代传统的乘法和加法。

在本文的代码中,广义矩阵乘法的定义是:

\(C_{ij} = \max_{k} (A_{ik} + B_{kj})\)

即,结果矩阵 C 的每个元素是 A 的第 i 行与 B 的第 j 列对应元素相加后的最大值,而不是传统的乘积之和。这种运算在某些算法问题中特别有用,例如求最长路径问题。

三、C++ 代码详解

现在我们来详细分析你提供的 C++ 代码,理解每个部分的作用和运行逻辑。

3.1 结构体定义

struct matrix{
int g[2][2];  // 存储2×2矩阵的二维数组

解释

  • struct关键字用于定义一个结构体类型。结构体是 C++ 中用户自定义的数据类型,可以包含不同类型的成员变量。

  • matrix是结构体的名称。

  • g[2][2]是一个 2 行 2 列的二维数组,用于存储矩阵的元素。g[i][j]表示矩阵第 i 行第 j 列的元素。

3.2 运算符重载:广义矩阵乘法

 matrix operator*(matrix b){ //广义矩阵积
matrix t; memset(t.g,-0x3f,sizeof(t.g));

解释

  • operator*是运算符重载,允许使用*运算符对matrix类型的对象进行操作。

  • matrix operator*(matrix b)声明了一个成员函数,该函数定义了matrix类型对象与另一个matrix对象b相乘的行为。

  • matrix t创建了一个临时矩阵t,用于存储乘法结果。

  • memset(t.g,-0x3f,sizeof(t.g))将矩阵t的所有元素初始化为 - 0x3f3f3f3f(约等于 - 1061109567)。这是一个非常小的数,作为初始值以便后续的最大值比较。

为什么初始化为 - 0x3f3f3f3f?

因为我们要在后续计算中取最大值,初始值必须足够小,确保第一个比较对象(不管是什么)都会比它大,从而正确更新结果。-0x3f3f3f3f 是一个常用的 “负无穷” 替代值,因为它的十六进制表示全为 0x3f 重复,而memset按字节填充,所以用-0x3f填充整个数组会得到一个非常小的数。

3.3 三重循环实现广义矩阵乘法

    for(int i=0; i<=1; ++i)
    for(int j=0; j<=1; ++j)
    for(int k=0; k<=1; ++k)
      t.g[i][j]=max(t.g[i][j],g[i][k]+b.g[k][j]);
    return t;
  }  

解释

  • 外层三层循环遍历所有可能的ijk组合。ij用于遍历结果矩阵t的行和列,k用于遍历中间索引。

  • 对于每个位置(i,j),计算g[i][k] + b.g[k][j]的最大值,其中k从 0 到 1。这相当于将传统矩阵乘法中的乘积替换为加法,将求和替换为求最大值。

  • t.g[i][j] = max(t.g[i][j], g[i][k] + b.g[k][j])确保每个位置的值是所有可能的k路径中的最大值。

三重循环的顺序

循环的顺序是i(行)、j(列)、k(中间索引),这与标准矩阵乘法的顺序相同。这是因为矩阵乘法的数学定义要求遍历所有可能的中间元素,以计算正确的行和列组合。

3.4 结构体数组声明

}mt[N],tr[N<<2];

解释

  • mt[N]声明了一个名为mtmatrix类型数组,包含N个元素。这个数组可能用于存储原始矩阵数据。

  • tr[N<<2]声明了另一个matrix类型数组tr,其大小为N<<2N<<2是按位左移操作,相当于N*4。这种大小通常用于线段树(一种数据结构),因为线段树通常需要 4 倍于原始数据大小的空间。

四、代码运行逻辑分析

为了更好地理解代码的运行逻辑,我们可以通过一个具体的例子来模拟代码的执行过程。

4.1 示例矩阵

假设有两个矩阵 A 和 B:

\(A = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}, \quad B = \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}\)

4.2 广义矩阵乘法计算过程

计算 C = A * B 的过程如下:

初始化矩阵 t

\(t = \begin{bmatrix} -∞ & -∞ \\ -∞ & -∞ \end{bmatrix}\)

计算 t.g [0][0]

  • k=0: 1 + 5 = 6 → max(-∞, 6) = 6

  • k=1: 2 + 7 = 9 → max(6, 9) = 9
    → t.g[0][0] = 9

    → t.g[0][0] = 9

计算 t.g [0][1]

  • k=0: 1 + 6 = 7 → max(-∞, 7) = 7

  • k=1: 2 + 8 = 10 → max(7, 10) = 10
    → t.g[0][1] = 10

    → t.g[0][1] = 10

计算 t.g [1][0]

  • k=0: 3 + 5 = 8 → max(-∞, 8) = 8

  • k=1: 4 + 7 = 11 → max(8, 11) = 11
    → t.g[1][0] = 11

    → t.g[1][0] = 11

计算 t.g [1][1]

  • k=0: 3 + 6 = 9 → max(-∞, 9) = 9

  • k=1: 4 + 8 = 12 → max(9, 12) = 12
    → t.g[1][1] = 12

    → t.g[1][1] = 12

最终结果矩阵 t

\(t = \begin{bmatrix} 9 & 10 \\ 11 & 12 \end{bmatrix}\)

4.3 与标准矩阵乘法的对比

如果使用标准矩阵乘法计算 A 和 B 的乘积,结果将是:

\(C = \begin{bmatrix} 19 & 22 \\ 43 & 50 \end{bmatrix}\)

这与广义矩阵乘法的结果明显不同,说明两种运算的应用场景也不同。

五、广义矩阵乘法的应用场景

你可能会问,这种广义矩阵乘法有什么实际用途呢?以下是一些常见的应用场景:

5.1 最长路径问题

在图论中,广义矩阵乘法可以用于求解图中经过若干条边的最长路径。假设有一个图,其邻接矩阵 A 中 A [i][j] 表示从节点 i 到节点 j 的边权。使用标准矩阵乘法,A²[i][j] 表示从 i 到 j 恰好经过 2 条边的路径数目;而使用广义矩阵乘法,A²[i][j] 则表示从 i 到 j 恰好经过 2 条边的最长路径长度。

5.2 动态规划优化

广义矩阵乘法可以用于优化某些动态规划问题。例如,对于斐波那契数列这样的递推关系,可以通过构造适当的转移矩阵,利用矩阵快速幂将时间复杂度从 O (n) 优化到 O (log n)。

5.3 状态转移

在状态转移问题中,矩阵乘法可以表示状态之间的转移关系。通过广义矩阵乘法,可以找到最优的状态转移路径,例如在机器人路径规划或状态机设计中。

六、矩阵快速幂

矩阵快速幂是将快速幂算法应用于矩阵乘法的一种技术,通常用于高效计算矩阵的高次幂。这在解决递推关系或动态规划问题时非常有用。

6.1 矩阵快速幂的实现思路

矩阵快速幂的基本思路与普通快速幂类似,但将数字的乘法替换为矩阵乘法。其步骤如下:

  1. 初始化结果矩阵为单位矩阵(类似于数字 1)。

  2. 将指数分解为二进制形式,通过不断平方矩阵并根据二进制位选择是否乘到结果中。

6.2 示例代码

以下是一个简单的矩阵快速幂示例代码框架:

matrix matrix_pow(matrix base, int power) {
    matrix result = identity_matrix; // 单位矩阵
    while (power > 0) {
        if (power % 2 == 1) {
            result = result * base; // 使用广义矩阵乘法
        }
        base = base * base; // 平方矩阵
        power /= 2;
    }
    return result;
}

七、总结与扩展

通过本文的学习,你应该已经掌握了以下内容:

  1. 矩阵的基本概念:包括矩阵的定义、表示方法和基本运算。

  2. 矩阵乘法规则:标准矩阵乘法和广义矩阵乘法的区别。

  3. C++ 结构体:如何定义和使用结构体来封装数据和操作。

  4. 运算符重载:如何重载*运算符以支持自定义类型的运算。

  5. 代码分析:如何理解和分析实现广义矩阵乘法的 C++ 代码。

7.1 进一步学习建议

如果你想进一步学习和应用矩阵快速幂和广义矩阵乘法,可以考虑以下方向:

  1. 动态规划优化:学习如何将动态规划问题转化为矩阵形式,利用矩阵快速幂加速计算。

  2. 图论应用:探索矩阵在图论中的更多应用,如最短路径、连通性分析等。

  3. 数据结构:了解如何将矩阵与其他数据结构(如线段树)结合使用,解决更复杂的问题。

  4. 线性代数基础:深入学习线性代数,了解矩阵的更多性质和应用。

7.2 完整代码示例

以下是一个完整的示例代码,包括矩阵定义、广义矩阵乘法、矩阵快速幂和示例使用:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

struct matrix{
  int g[2][2];  // 存储2×2矩阵的二维数组

  matrix operator*(matrix b){ //广义矩阵乘积
    matrix t; 
    memset(t.g, -0x3f, sizeof(t.g)); // 初始化为负无穷
    for(int i=0; i<=1; ++i)
      for(int j=0; j<=1; ++j)
        for(int k=0; k<=1; ++k)
          t.g[i][j] = max(t.g[i][j], g[i][k] + b.g[k][j]);
    return t;
  }

  // 打印矩阵内容
  void print() {
    for(int i=0; i<2; ++i) {
      for(int j=0; j<2; ++j) {
        cout << g[i][j] << " ";
      }
      cout << endl;
    }
  }
};

// 矩阵快速幂
matrix matrix_pow(matrix base, int power) {
    matrix result = {{{1, -0x3f}, {-0x3f, 1}}}; // 初始化为单位矩阵(根据广义乘法定义)
    while (power > 0) {
        if (power % 2 == 1) {
            result = result * base;
        }
        base = base * base;
        power /= 2;
    }
    return result;
}

int main() {
    // 示例矩阵
    matrix a = {{{1, 2}, {3, 4}}};
    matrix b = {{{5, 6}, {7, 8}}};

    // 计算广义矩阵乘积
    matrix c = a * b;
    cout << "广义矩阵乘积结果:" << endl;
    c.print();

    // 计算矩阵快速幂示例(a的3次方)
    matrix d = matrix_pow(a, 3);
    cout << "矩阵快速幂结果:" << endl;
    d.print();

    return 0;
}

struct

输出结果

广义矩阵乘积结果:
9 10 
11 12 
矩阵快速幂结果:
21 22 
25 26 

通过不断学习和实践,你将能够更深入地理解矩阵和矩阵快速幂的应用,为解决更复杂的算法问题打下坚实的基础。希望本文对你的学习有所帮助!

**参考资料
**

[1] 第一章 矩阵及其应用\n矩阵是代数学中最重要的基本概念之一,(pdf) http://web.xidian.edu.cn/rxli/files/20110822_161640.pdf

[2] 矩阵[由排成m行和1列的真实的数字或元素所组成的矩阵]_百科 https://m.baike.com/wiki/%E7%9F%A9%E9%98%B5/6438799?baike_source=doubao

[3] 【漫话机器学习系列】116.矩阵(Matrices)_矩阵的表示方法-CSDN博客 https://blog.csdn.net/IT_ORACLE/article/details/145978323

[4] 2025考研数学(一)线性代数大纲原文解析_中公教育网 http://m.offcn.com/kaoyan/2024/0923/273528.html

[5] 《3D 数学基础:图形与游戏开发》七、矩阵7.1 矩阵——数学定义 7.1.1 矩阵的维度和记法 矩阵的维度被定义为它包 - 掘金 https://juejin.cn/post/7473331107787849763

[6] 矩阵 | 中文数学 Wiki | Fandom https://math.fandom.com/zh/wiki/%E7%9F%A9%E9%98%B5

[7] 矩阵及其运算:深度学习中的核心概念_51CTO学堂_专业的IT技能学习平台 https://edu.51cto.com/article/note/17810.html

[8] C++结构体,学后梳理,适合新手-CSDN博客 https://blog.csdn.net/2401_84412323/article/details/142402803

[9] C++入门之结构体_c++结构体简单例子-CSDN博客 https://blog.csdn.net/deghgjgcng/article/details/116447780

[10] c++入门-结构体c++结构体 结构体基本概念 结构体属于用户自定义的数据类型,允许用户存储不同的数据类型 结构体定义和 - 掘金 https://juejin.cn/post/7225989692561637433

[11] c++基础入门自学笔记总结3---结构体 - 书文阁下 - 博客园 https://www.cnblogs.com/shugexia-blogs/p/16726934.html

[12] C++入门教程-12.结构体-抖音 https://www.iesdouyin.com/share/video/7360605171598019867/?did=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&from_aid=1128&from_ssr=1&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&mid=7360605361017391884&region=&scene_from=dy_open_search_video&share_sign=Rqe3_fOrM1GJLikR6Owkycofjfp62xP7hiS93EpZ2qg-&share_version=280700&titleType=title&ts=1752494461&u_code=0&video_share_track_ver=&with_sec_did=1

[13] 结构体的出现对于编程界来说具有非常深远的意义,一起来看下吧-抖音 https://www.iesdouyin.com/share/video/7484185956510125369/?did=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&from_aid=1128&from_ssr=1&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&mid=7484185806119176994&region=&scene_from=dy_open_search_video&share_sign=yRYM3CUZaPus0dS_8wIGhNgFfCjq_0jfXebOCoMMaoI-&share_version=280700&titleType=title&ts=1752494461&u_code=0&video_share_track_ver=&with_sec_did=1

[14] 零基础学习C++编程第143集struct结构体-结构体指针使用规则-抖音 https://www.iesdouyin.com/share/video/7417907468581211430/?did=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&from_aid=1128&from_ssr=1&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&mid=7417907257146411812&region=&scene_from=dy_open_search_video&share_sign=M.3M3orBxVTRN13YA9XZiYZOiZJYQczHLVue5MvisG0-&share_version=280700&titleType=title&ts=1752494461&u_code=0&video_share_track_ver=&with_sec_did=1

[15] 6.12 ACM-ICPC动态规划算法 动态 DP_动态dp-CSDN博客 https://blog.csdn.net/tang7mj/article/details/138302787

[16] AcWing 345 牛站_的技术博客_51CTO博客 https://blog.51cto.com/u_3044148/5158005

[17] pytorch 怎么拿到q k v矩阵_mob64ca14133dc6的技术博客_51CTO博客 https://blog.51cto.com/u_16213696/13288741

[18] GEMMs :指广义矩阵乘法(General Matrix Multiply)-CSDN博客 https://blog.csdn.net/weixin_46251155/article/details/137913282

[19] 【PyTorch】torch.matmul() 函数: 矩阵乘法(矩阵点积)_torch.matmul运算-CSDN博客 https://blog.csdn.net/u013172930/article/details/146964793

[20] 使用 NVIDIA 数学库加速 GPU 应用程序 - NVIDIA 技术博客 https://developer.nvidia.com/zh-cn/blog/accelerating-gpu-applications-with-nvidia-math-libraries/

[21] 一种基于状态轮询的非阻塞式多线程矩阵乘法处理方法与流程 https://www.xjishu.com/zhuanli/55/202411054692.html

[22] 【动态规划 矩阵快速幂】P1357 花园|省选-_p1357花园-CSDN博客 https://blog.csdn.net/he_zhidan/article/details/145966302

[23] 算法【乘法快速幂、矩阵快速幂】-CSDN博客 https://blog.csdn.net/W_O_Z/article/details/145371970

[24] (详解)矩阵快速幂详解与常见转移矩阵的构造-CSDN博客 https://blog.csdn.net/jisuanji2606414/article/details/124073979

[25] 【动态规划 矩阵快速幂】P8624 [蓝桥杯 2015 省 AB] 垒骰子|普及+-CSDN博客 https://blog.csdn.net/he_zhidan/article/details/145886056

[26] 动态规划系列-第N个斐波那契数-抖音 https://www.iesdouyin.com/share/video/7499012443381730560/?did=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&from_aid=1128&from_ssr=1&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&mid=7499012944118975259&region=&scene_from=dy_open_search_video&share_sign=AzY5xlP3tNXhv1HqnMpwzoKVa35c8sEp13zlpG0ucQA-&share_version=280700&titleType=title&ts=1752494537&u_code=0&video_share_track_ver=&with_sec_did=1

[27] 《算法初步》课程第六章第三节:计算斐波那契数(矩阵法)-抖音 https://www.iesdouyin.com/share/video/7057033799896419587/?did=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&from_aid=1128&from_ssr=1&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&mid=0&region=&scene_from=dy_open_search_video&share_sign=dKBn1ByxhKlhAuockRTyeTjEWqKlMsYkLsO20Diw5yA-&share_version=280700&titleType=title&ts=1752494537&u_code=0&video_share_track_ver=&with_sec_did=1

[28] #算法 #动态规划 矩阵连乘次数(上)-抖音 https://www.iesdouyin.com/share/video/7314922287445085478/?did=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&from_aid=1128&from_ssr=1&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&mid=7314922490210323209&region=&scene_from=dy_open_search_video&share_sign=BnYXXGofv_90oqq9Ymj9r3Csj9qaEeH2FDEgs0QRPw0-&share_version=280700&titleType=title&ts=1752494537&u_code=0&video_share_track_ver=&with_sec_did=1

(注:本人第一次写不好请指出&&结合了一下ai)

posted @ 2025-07-14 20:28  liduo  阅读(159)  评论(0)    收藏  举报