首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

三對角矩陣追趕法求解線性方程組:Thomas 算法 C++ 實現與工程化詳解

     編輯:關於C語言

三對角線性系統 Ax = b 廣泛存在於有限差分、樣條插值、流體動力學等領域。追趕法以 O(n) 時間複雜度和 O(n) 空間複雜度,成為求解此類系統的黃金標準。本文深度解析一個完整的 C++ 實現,涵蓋 LU 分解、前向消去、後向代入、邊界處理等核心環節。

三對角矩陣結構與追趕法原理

矩陣 A 僅主對角線 d、次對角線 a、超對角線 c 非零:

[ d₁  c₁   0   ...   0  ]
[ a₂  d₂  c₂   ...   0  ]
[  0  a₃  d₃   ...   0  ]
[ ...                cₙ₋₁]
[  0   0   0   aₙ  dₙ  ]

追趕法本質是不帶主元選擇的 LU 分解:A = LU,其中 L 為單位下雙對角,U 為上雙對角。

演算法三階段

1. LU 分解(前向掃描)

p[1] = d[1];
q[1] = c[1] / d[1];
for (k=2; k

關鍵點: 僅需存儲 p[] (U主對角) 和 q[] (U超對角),L 的次對角隱含在計算中。

2. 前向代入求解 Ly = b

y[1] = b[1] / d[1];
Iy[1] = -a[1] / d[1];             // 為後續邊界修正準備
for (k=2; k

這裡 Iy[] 實際是求解 L z = eₙ 的中間量,用於處理週期性邊界條件或修正最後一行。

3. 後向代入與邊界修正

x[n-1] = y[n-1];  Ix[n-1] = Iy[n-1];
for (k=n-2; k>0; k--) {
    x[k] = y[k] - q[k] * x[k+1];
    Ix[k] = Iy[k] - q[k] * Ix[k+1];
}
// 修正最後一個未知數 x[n](利用週期/邊界條件)
x[n] = (b[n] - c[n]*x[1] - a[n]*x[n-1]) / (c[n]*Ix[1] + a[n]*Ix[n-1] + d[n]);
for (k=1; k

這段代碼處理了非標準三對角系統(首尾行有額外非零元素 c[n], a[n]),通過Sherman-Morrison 公式思想修正解向量。

測試案例與結果分析

// 系統參數 n=50
a[k]=1, c[k]=1, d[k]=4 (d[1]=2), b[k]=k+1

// 部分輸出
The roots are: (-6.4282, 2.31175, 0.18121, 0.963411, 0.965146, 1.17601,
  1.33083, 1.50067, 1.66649, 1.83338, 1.99999, 2.16667, 2.33333, 2.5,
  2.66667, 2.83333, 3, 3.16667, 3.33333, 3.5, 3.66667, 3.83333, 4,
  4.16667, 4.33333, 4.5, 4.66667, 4.83333, 5, 5.16667, 5.33333, 5.5,
  5.66667, 5.83333, 6, 6.16667, 6.33333, 6.5, 6.66666, 6.83334, 6.99997,
  7.16677, 7.33293, 7.5015, 7.66108, 7.85418, 7.92219, 8.45706, 7.24957, 12.5447)

解向量呈現近線性增長趨勢(理論解應為 xₖ ≈ k),邊界處因修正條件出現波動,末端 x₅₀=12.54 偏離預期,提示邊界條件實現需仔細驗證。

數值穩定性與適用條件

  • 嚴格對角佔優:|dᵢ| > |aᵢ| + |cᵢ| 保證無需主元選擇
  • M-矩陣:dᵢ>0, aᵢ≤0, cᵢ≤0 且對角佔優 → 穩定
  • 病態系統:條件數大時雙精度可能失效,需考慮迭代精煉

現代化封裝建議

class TridiagonalSolver {
    std::vector a_, d_, c_;  // 次對角、主對角、超對角
    std::vector p_, q_;      // LU 分解緩存
public:
    TridiagonalSolver(int n) : a_(n+1), d_(n+1), c_(n+1), p_(n+1), q_(n+1) {}
    void factorize();                // LU 分解
    std::vector solve(const std::vector& b); // 前向+後向
    // 支援週期性邊界、分塊三對角擴展
};

工程避坑指南

  1. 索引基準:代碼使用 1-based 索引,轉換為 0-based 時注意邊界
  2. 除零保護:p[k] < 1e-8 閾值應關聯機器精度與條件數
  3. 記憶體佈局:連續向量優於分散指針,利用快取預取
  4. 邊界條件:週期性、Neumann、Dirichlet 不同邊界需對應修改最後兩行

總結

追趕法是線性代數直接法中罕見的 O(n) 算法,其優雅在於將高斯消去的 O(n³) 降維為三條向量遞推。掌握其 LU 分解視角、前向/後向代入、邊界修正技巧,不僅能高效求解三對角系統,更能理解稀疏矩陣直接法的核心思想——這正是有限元、CFD、計算金融等領域高性能求解器的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved