记录一下追赶法解特殊方程组,设有
n
n
n阶方程组
A
x
=
d
\mathbf{A}x=d
Ax=d,其中
A
\mathbf{A}
A为三对角矩阵,即
A
=
[
b
1
c
1
a
2
b
2
c
2
⋱
⋱
⋱
a
n
−
1
b
n
−
1
c
n
−
1
a
n
b
n
]
,
d
=
[
d
1
d
2
⋮
d
n
−
1
d
n
]
\mathbf{A} = \left[
对矩阵
A
\mathbf{A}
A进行克洛托分解(
L
U
LU
LU分解),得到
L
=
[
l
1
v
2
l
2
⋱
⋱
v
n
−
1
l
n
−
1
v
n
l
n
]
,
U
=
[
1
u
1
1
u
2
⋱
⋱
1
u
n
−
1
1
u
n
]
\mathbf{L} = \left[
因此
A
x
=
d
\mathbf{A}x=d
Ax=d等价于求解
L
y
=
d
Ly=d
Ly=d和
U
x
=
y
Ux=y
Ux=y,于是可以推得追赶法算法过程如下:
1.计算
l
i
l_{i}
li,
u
i
u_{i}
ui递推公式。
l
1
=
b
1
,
l
i
=
b
i
−
a
i
u
i
−
1
,
i
=
2
,
3
,
4
,
…
,
n
u
1
=
c
1
/
b
1
,
u
i
=
c
i
/
l
i
,
i
=
2
,
3
,
4
,
…
,
n
l_{1} = b_{1}, \quad l_{i} = b_{i} - a_{i}u_{i-1}, \quad i=2,3,4,\dots,n\\ u_{1} = c_{1} / b_{1},\quad u_{i} = c_{i} / l{i},\quad\quad i=2,3,4,\dots,n
l1=b1,li=bi−aiui−1,i=2,3,4,…,nu1=c1/b1,ui=ci/li,i=2,3,4,…,n
2.求解
L
y
=
d
Ly=d
Ly=d。
y
1
=
d
1
/
b
1
,
y
i
=
(
d
i
−
a
i
y
i
−
1
)
/
l
i
,
i
=
2
,
3
,
4
,
…
,
n
y_{1} = d_{1}/b_{1}, \quad y_{i} = (d_{i} - a_{i}y_{i-1})/l_{i}, \quad i=2,3,4,\dots,n
y1=d1/b1,yi=(di−aiyi−1)/li,i=2,3,4,…,n
3.求解
U
x
=
y
Ux=y
Ux=y。
x
n
=
y
n
,
x
i
=
y
i
−
u
i
x
i
+
1
,
i
=
n
−
2
,
n
−
2
,
…
,
1
x_{n} = y_{n}, \quad x_{i} = y_{i} - u_{i}x_{i+1}, \quad i=n-2,n-2,\dots,1\\
xn=yn,xi=yi−uixi+1,i=n−2,n−2,…,1
故可将上述算法过程转换成代码:
追赶法MATLAB程序代码
function x = tridiagsolver(a, b, c, d)
n = length(b);
l(1) = b(1);
y(1) = d(1) / l(1);
u(1) = c(1) / l(1);
for ii = 2 : n
l(ii) = b(ii) - a(ii - 1) * u(ii - 1);
y(ii) = (d(ii) - y(ii - 1) * a(ii - 1)) / l(ii);
if ii <= n-1
u(ii) = c(ii) / l(ii);
end
end
x(n) = y(n);
for ii = n-1 : -1 : 1
x(ii) = y(ii) - u(ii) * x(ii + 1);
end
追赶法C++程序代码
/*************************************************************************
void tridiagsolver(double *dst, double *a, double *b, double *c, double *d, int num)
功能: 追赶法求解三角矩阵
参数:
dst: 输出结果
a: 稀疏矩阵最下边部分的元素
b: 稀疏矩阵中间部分的元素
c: 稀疏矩阵最上边部分的元素
d: 右端向量
num: 矩阵大小
返回值: 无
*************************************************************************/
void tridiagsolver(double *dst, double *a, double *b, double *c, double *d, int num)
{
double *l = new double[num];
double *y = new double[num];
double *u = new double[num - 1];
// 追过程
l[0] = b[0];
y[0] = d[0] / l[0];
u[0] = c[0] / l[0];
for (int i = 1; i < num; i++)
{
l[i] = b[i] - a[i-1] * u[i-1];
y[i] = (d[i] - y[i-1] * a[i-1]) / l[i];
if (i < num - 1)
u[i] = c[i] / l[i];
}
// 赶过程
dst[num-1] = y[num-1];
for (int i = num-2; i >= 0; i--)
{
dst[i] = y[i] - u[i] * dst[i+1];
}
delete l;
delete y;
delete u;
}
需要注意的是,程序中的代码和算法求解过程存在略微差异,是由于存储对三角a,b,c的数组大小不一致引起。如果输入的数组大小一致,则需要对代码进行相应修改。如图1所示的是对三角方程的求解过程。
参考文献:
[1] 现代数值计算/同济大学计算数学教研室编著.——2版. ——北京:人民邮电出版社,2021.12冲印