追赶法的优点是对三对角、五对角、七对角等矩阵线性方程组求解的快速有效办法,而三对角矩阵在有限差分格式中出现的太多了,除此之外,其在物理、工程等领域也都会用到三对角求解的追赶法。
追赶法的基本思想与高斯消元法及三角分解法相同,只是由于系数中出现了大量的零,计算中可将它们撇开,从而使得计算公式简化,大大减少了计算量。这是一种特殊的稀疏矩阵,非零元素集中分布在主对角线及其相邻两条对角线上,称为三对角矩阵。
追赶法只是针对系数矩阵为三对角阵的方程组,因此是一种特殊的方程组。此方法效率较高,不过不适用于一般的线性方程组。
方程组,又称联立方程。把若干个方程合在一起研究,使其中的未知数同时满足每一个方程的一组方程。能同时满足方程组中每个方程的未知数的值,称为方程组的“解”。求出它所有解的过程称为“解方程组”。
方程组,又称联立方程,是两个或两个以上含有多个未知数的方程联立得到的组合。未知数的值称为方程组的,求方程组根的过程称为“解方程组”。一般在方程式的左边加大括号标注。
using System;
namespace Zhou.CSharp.Algorithm
{
///
/// 求解线性方程组的类 LEquations
/// 原作 周长发
/// 改编 深度混淆
///
public static partial class LEquations
{
///
/// 求解三对角线方程组的追赶法
///
/// 指定的系数矩阵
/// 指定的常数矩阵
/// Matrix对象,返回方程组解矩阵
///
public static bool GetRootsetTriDiagonal(Matrix mtxLECoef, Matrix mtxLEConst, Matrix mtxResult)
{
int k, j;
double s;
// 将常数矩阵赋给解矩阵
mtxResult.SetValue(mtxLEConst);
double[] pDataConst = mtxResult.GetData();
int n = mtxLECoef.GetNumColumns();
if (mtxLECoef.GetNumRows() != n)
{
return false;
}
// 为系数矩阵对角线数组分配内存
double[] pDiagData = new double[3 * n - 2];
// 构造系数矩阵对角线元素数组
k = j = 0;
if (k == 0)
{
pDiagData[j++] = mtxLECoef.GetElement(k, k);
pDiagData[j++] = mtxLECoef.GetElement(k, k + 1);
}
for (k = 1; k < n - 1; ++k)
{
pDiagData[j++] = mtxLECoef.GetElement(k, k - 1);
pDiagData[j++] = mtxLECoef.GetElement(k, k);
pDiagData[j++] = mtxLECoef.GetElement(k, k + 1);
}
if (k == n - 1)
{
pDiagData[j++] = mtxLECoef.GetElement(k, k - 1);
pDiagData[j++] = mtxLECoef.GetElement(k, k);
}
// 求解
for (k = 0; k <= n - 2; k++)
{
j = 3 * k;
s = pDiagData[j];
// 求解失败
if (Math.Abs(s) < float.Epsilon) // Math.Abs(s) + 1.0 == 1.0)
{
return false;
}
pDiagData[j + 1] = pDiagData[j + 1] / s;
pDataConst[k] = pDataConst[k] / s;
pDiagData[j + 3] = pDiagData[j + 3] - pDiagData[j + 2] * pDiagData[j + 1];
pDataConst[k + 1] = pDataConst[k + 1] - pDiagData[j + 2] * pDataConst[k];
}
s = pDiagData[3 * n - 3];
if (Math.Abs(s) < float.Epsilon)// s == 0.0)
{
return false;
}
// 调整
pDataConst[n - 1] = pDataConst[n - 1] / s;
for (k = n - 2; k >= 0; k--)
{
pDataConst[k] = pDataConst[k] - pDiagData[3 * k + 1] * pDataConst[k + 1];
}
return true;
}
}
}