1 2 3 4
5 6 7 8
9 10 11 12
《计算机程序设计》
计算机学院计算机研究所编译系统研究室
~/course
~/course/main.cpp
main.cpp
,随堂编程练习的代码请直接在此文件中编辑学习目标
arrayparam.cpp
明察秋毫
matrix
,matrix[i][j]
将等价于*(matrix + i * N + j)
解决办法
p
指向MxN矩阵matrix
,matrix[i][j]
将等价于*(p + i * N + j)
linearize.cpp
#include <iostream>
void printMatrix(double *matrix, int rows, int cols) {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j)
std::cout << matrix[i * cols + j] << " ";
std::cout << std::endl;
}
}
int main() {
int m = 0, n = 0;
std::cin >> m >> n;
double *matrix = new double[m * n];
for (int i = 0; i < m * n; ++i)
matrix[i] = i + 1;
printMatrix(matrix, m, n);
delete[] matrix;
return 0;
}
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & 1 & 2 & 8 \\ 0 & 0 & 1 & 3 \end{array} \right] \]
\[x = 1, y = 2, z = 3\]
\[Ax=b, A \in \mathbb{R}^{n \times n}, b \in \mathbb{R}^n\]
\[\overset{\text{写作增广矩阵}} \Longrightarrow\]
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
实现方式
double *Ab
:增广矩阵首地址,(2)int n
:未知数个数(增广矩阵行数)实现方式
函数签名 | 描述 |
---|---|
void rswap(double *Ab, int n, int i, int j) |
交换第i、j行 |
void rscale(double *Ab, int n, int i, double k) |
将第i行乘以k |
void radd(double *Ab, int n, int i, int j, double k) |
将i行加上j行的k倍 |
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[\overset{\text{交换第2、3行}} \Longrightarrow\]
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 9 & 10 & 10 & 59 \\ 5 & 6 & 7 & 38 \end{array} \right] \]
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[\overset{\text{第1行倍乘-5}} \Longrightarrow\]
\[ \left[ \begin{array}{ccc:c} -5 & -10 & -15 & -70 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[\overset{\text{第2行加上第1行的-5倍}} \Longrightarrow\]
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & -4 & -8 & -32 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
明察秋毫
初等行变换不改变线性方程组的解(可能打乱解向量中各分量的顺序)
初等行变换
void rswap(double *Ab, int n, int i, int j) {
for (int k = 0; k < n + 1; ++k) {
double temp = Ab[i * (n + 1) + k];
Ab[i * (n + 1) + k] = Ab[j * (n + 1) + k];
Ab[j * (n + 1) + k] = temp;
}
}
void rscale(double *Ab, int n, int i, double k) {
// ================= begin =================
// ================= begin =================
}
void radd(double *Ab, int n, int i, int j, double k) {
// ================= begin =================
// ================= end =================
}
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & 1 & 2 & 8 \\ 0 & 0 & 1 & 3 \end{array} \right] \]
明察秋毫
还原矩阵由上三角系数矩阵与右端项组成
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 5 & 6 & 7 & 38 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[ \overset{\text{add(2,1,-5)}}\Longrightarrow \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & -4 & -8 & -32 \\ 9 & 10 & 10 & 59 \end{array} \right] \]
\[ \overset{\text{add(3,1,-9)}}\Longrightarrow \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & -4 & -8 & -32 \\ 0 & -8 & -17 & -67 \end{array} \right] \]
\[ \overset{\text{scale(2,-0.25)}}\Longrightarrow \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & 1 & 2 & 8 \\ 0 & -8 & -17 & -67 \end{array} \right] \]
\[ \overset{\text{add(3,2,8)}}\Longrightarrow \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & 1 & 2 & 8 \\ 0 & 0 & -1 & -3 \end{array} \right] \]
\[ \overset{\text{scale(3,-1)}}\Longrightarrow \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & 1 & 2 & 8 \\ 0 & 0 & 1 & 3 \end{array} \right] \]
通过初等行变换将增广矩阵转化为还原矩阵
void rswap(double *Ab, int n, int i, int j);
void rscale(double *Ab, int n, int i, double k);
void radd(double *Ab, int n, int i, int j, double k);
void triangularize(double *Ab, int n) {
for (int i = 0; i < n; ++i) {
// ================= begin =================
// 倍乘第i行主元使之为1
// 消除第i行主元下方的元素
// ================= end =================
}
}
实现方式
还原矩阵存储在原始增广矩阵的内存中(前n列,系数部分),不额外分配内存
\[ \left[ \begin{array}{ccc:c} 1 & 2 & 3 & 14 \\ 0 & 1 & 2 & 8 \\ 0 & 0 & 1 & 3 \end{array} \right] \]
回代求解
实现方式
解向量存储在原始增广矩阵的内存中(最后1列,右端项部分),不额外分配内存
\[E_{1,3} = \begin{bmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}, \]
\[ A = \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{bmatrix}\Rightarrow \]
\[ E_{1,3}A = \begin{bmatrix} 9 & 10 & 11 & 12 \\ 5 & 6 & 7 & 8 \\ 1 & 2 & 3 & 4 \\ 13 & 14 & 15 & 16 \end{bmatrix} \]
明察秋毫
\(E_{i,j}\)由单位矩阵\(E\)第\(i\)列与第\(j\)列互换得到
\[E_2^{-2} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -2 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]
\[ A = \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{bmatrix} \]
\[ E_{2}^{-2}A = \begin{bmatrix} 1 & 2 & 3 & 4 \\ -10 & -12 & -14 & -16 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{bmatrix} \]
明察秋毫
\(E_i^\alpha\)由单位矩阵\(E\)第\(i\)列倍乘\(\alpha\)得到
\[E_{3,1}^{-2} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ -2 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]
\[ A = \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{bmatrix} \]
\[ E_{3,1}^{-2}A = \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 7 & 6 & 5 & 4 \\ 13 & 14 & 15 & 16 \end{bmatrix} \]
明察秋毫
\(E_{i,j}^\alpha\)由单位矩阵\(E\)第\(i\)行加上第\(j\)行的\(\alpha\)倍得到
正向消元由一系列初等行变换操作组成
\[L_K \cdots L_2 L_1 [A|b] = [U|b']\]
其中,\(L_{k}\)(\(k=1,2,\cdots,K\))为初等行变换,\(U\)为上三角矩阵
由\(L_K \cdots L_2 L_1 A = U\)可得
\[A = L_1^{-1} L_2^{-1} \cdots L_K^{-1} U = LU\]
定理
定理 1 矩阵\(L=L_1^{-1} L_2^{-1} \cdots L_K^{-1}\)是一个下三角矩阵
原线性方程组\(Ax=b\)可写作
\[LUx=b\]
令\(y=Ux\),原问题可分解为两个三角线性方程组求解问题
\[Ly=b, Ux=y\]
明察秋毫
LU分解法求解线性方程组的步骤:
令
\[L= \begin{bmatrix} L_{11} & 0\\ L_{21} & L_{22} \end{bmatrix} \]
\[ U= \begin{bmatrix} U_{11} & U_{12}\\ 0 & U_{22} \end{bmatrix} \]
\[ A= \begin{bmatrix} A_{11} & A_{12}\\ A_{21} & A_{22} \end{bmatrix} \]
由\(A=LU\)可得
\[ \begin{aligned} A_{11} &= L_{11}U_{11} \\ A_{12} &= L_{11}U_{12} \\ A_{21} &= L_{21}U_{11} \\ A_{22} &= L_{21}U_{12} + L_{22}U_{22} \end{aligned} \]
设置分块大小使\(L_{11} \in \mathbb{R}^{1 \times 1}\)
\[ \begin{aligned} A_{11} &= L_{11}U_{11} \\ A_{12} &= L_{11}U_{12} \\ A_{21} &= L_{21}U_{11} \\ A_{22} &= L_{21}U_{12} + L_{22}U_{22} \end{aligned} \]
\[\Rightarrow\]
\[ \begin{aligned} l_{11} = 1 &, u_{11} = a_{11} \\ U_{12} &= A_{12} \\ L_{21} &= A_{21} / u_{11} \\ L_{22}U_{22} &= A_{22} - L_{21}U_{12} \end{aligned} \]
明察秋毫
\[ \left[ \begin{array}{c:cc} 2 & 3 & 1 \\ \hdashline 4 & 7 & 4 \\ -2 & -2 & 3 \end{array} \right] \]
\[\Rightarrow \left[ \begin{array}{c:cc} 2 & 3 & 1 \\ \hdashline 2 & 7 & 4 \\ -1 & -2 & 3 \end{array} \right] \]
\[\Rightarrow \left[ \begin{array}{c:cc} 2 & 3 & 1 \\ \hdashline 2 & 1 & 2 \\ -1 & 1 & 4 \end{array} \right] \]
\[\Rightarrow \left[ \begin{array}{cc:c} 2 & 3 & 1 \\ 2 & 1 & 2 \\ \hdashline -1 & 1 & 4 \end{array} \right] \]
\[\Rightarrow \left[ \begin{array}{cc:c} 2 & 3 & 1 \\ 2 & 1 & 2 \\ \hdashline -1 & 1 & 2 \end{array} \right] \]
\[\Rightarrow L = \left[ \begin{array}{ccc} 1 & 0 & 0 \\ 2 & 1 & 0 \\ -1 & 1 & 1 \end{array} \right], U = \left[ \begin{array}{ccc} 2 & 3 & 1 \\ 0 & 1 & 1 \\ 0 & 0 & 2 \end{array} \right] \]
LU分解算法
实现方式
--- config: look: handDrawn themeVariables: fontSize: 20px --- mindmap 线性方程组求解 多维数组索引的线性化 方式同多维数组索引寻址 经典高斯消元法 增广矩阵 初等行变换 正向消元 还原矩阵 回代求解 LU分解算法 初等行变换的矩阵表示 LU分解法原理 LU分解算法与实现
学习目标
计算机程序设计