解線性方程組的直接方法 ------ 三角分解法

矩陣分解 三角分解(LU分解) - billbliss的專欄 - CSDN博客  https://blog.csdn.net/billbliss/article/details/78559289

矩陣的三角分解其基本原理可見上面的博客鏈接(寫的很好,此處不再贅述)。

本博客主要是給出三角分解的C語言實現過程。

這裏舉出的計算實例如下所示:

\begin{bmatrix} 1 & 2 &3 \\ 2 & 5 &2 \\ 3 & 1&5 \end{bmatrix}\begin{bmatrix} x_{1}\\ x_{2}\\ x_{3} \end{bmatrix}=\begin{bmatrix} 14\\ 18\\ 20 \end{bmatrix}

1. 我們採用的第一種方法是,給L矩陣和U矩陣在main函數中進行初始化。然後傳入到子函數中進行賦值。

/*我們在這裏來創建一個函數,來實現三角分解法
    以下函數的參數中,所有名爲: Arr是方程組的稀釋矩陣
                                  L是存儲三角分解的下三角矩陣的內存空間
                                  U是存儲三角分解的上三角矩陣的內存空間
                                  N 是矩陣的階數  */

void Triangle_decomp(double (*Arr)[3], double (*L)[3], double (*U)[3], int N){
    // 對於三角分解的方式是進行先是行的賦值,然後是列的賦值
    // 首先要記得L是單位下三角矩陣,U是上三角矩陣
    // 對於三角分解的方式是先行後列,也就是說需要先確定U的一行,然後才能確定L的一列

    // 首先對於U的第一行可以直接賦值
    for(int i=0; i<N; i++) U[0][i] = Arr[0][i];
    // 然後接下來我們需要先給L中的第一列進行賦值
    for(int i=0; i<N; i++){
        L[i][i] = 1;
        L[i][0] = Arr[i][0] / Arr[0][0];
    }
    // 接下來我們來進行後面數組的賦值
    double sum_val = 0.0;
    for(int i=1; i<N; i++){
        // 然後來進行U的行的賦值.
        // 我們的求和是對應U的上面的所有的行
        // 我們這裏需要遍歷上面的行,並求和
        for(int d=i; d<N; d++){
            sum_val = 0.0;
            // 這裏遍歷的d是對應的列上的索引,但是對應的d的起始索引應該是什麼呢???
            for(int row_i=i-1; row_i>=0; row_i--){
                sum_val += L[i][row_i] * U[row_i][d];
            }
        // 然後我們來得到對應的L上的元素
        U[i][d] = Arr[i][d] - sum_val;
        }
        // 當跳出循環後,便完成了U的行的賦值
        // 當進行L的賦值之後,對應的遍歷i變成了對應的列索引
        for(int row_i=i+1; row_i<N; row_i++){
            // 這裏的循環是對應的L中的行,接下來該怎麼做?
            sum_val = 0.0;
            for(int d=i-1; d>=0; d--){ // 這裏的d是對應的列索引
                sum_val += L[row_i][d] * U[d][i];
            }
        L[row_i][i] = (Arr[row_i][i] - sum_val) / U[i][i];
        }
    }
}

運算結果如下圖:

2. 我們採用的第二種方法是直接將L中的元素和U中的元素寫入到Arr矩陣中去.

/*接下來我們來創建一個方法,來計算生成新的Arr數組*/
void Triangle_decomp01(double (*Arr)[3], int N){
    // 本方法是爲了實現將係數矩陣中的具體內容寫入到原係數矩陣中去
    // 首先第一行不去變化,因爲原L中的對角線上元素將不再出現
    // 接下來處理第一列,對於第一列元素,
    for(int i=1; i<N; i++) Arr[i][0] /= Arr[0][0];
    double sum_val = 0.0;
    // 接下來該是先去處理行上的元素,然後再去處理列上的元素
    for(int i=1; i<N; i++){
        // 接下來首先需要進行列上元素的遍歷,對於列上元素的起始索引,應該是當前的行數
        for(int col_i=i; col_i<N; col_i++){
            sum_val = 0.0;
            // 接下來進行求和計算,求和是當前行以上的所有的行
            for(int d=i-1; d>=0; d--){
                sum_val += Arr[i][d] * Arr[d][col_i];
            }
        // 接下來來計算對應的U上的元素
        // 對於U上對應位置上的元素,我們只需要將原索引上的值減去sum_val即可
        Arr[i][col_i] -= sum_val;
        }

        // 接下來我們需要做的便是來處理L的列上的元素
        // 當我們來遍歷列上的元素時,對應的i將會轉爲遍歷的列上
        for(int row_i=i+1; row_i<N; row_i++){ // 接下來首先需要遍歷的便是行
            // 接下來該是來進行求和了
            sum_val = 0.0;
            for(int col_i=i-1; col_i>=0; col_i--){
                // 這裏遍歷的col_i 是在L中對應的列
                sum_val += Arr[row_i][col_i] * Arr[col_i][i];
            }
        Arr[row_i][i] = (Arr[row_i][i]-sum_val) / Arr[i][i];
        }
    }
}

運算結果見下圖:

3. 我們採用的第三種方式是,將係數矩陣寫爲1D,並將L中的數據和U中的數據覆蓋到原Arr中去。

/*接下來創建一個方法,該方法將採用1D的係數矩陣來進行方程組的求解*/
void Triangle_decomp02(double *Arr, int N){
    // 第一行中的所有元素將不會再改變,
    // 我們要做的是先來處理第一列上的元素
    for(int i=1; i<N; i++){
        // 這裏的遍歷是第一列上的索引
        Arr[i*N+0] = Arr[i*N+0] / Arr[0];
    }
    // 接下來我們要做的便是該去進行後續的行的數據操作了
    // 首先遍歷的是當前要處理的行
    double sum_val = 0.0;
    for(int i=1; i<N; i++){
        // 內部的循環應該首先是列,因爲已經制定了要處理的行
        // 接下來需要首先指定我們要處理的列
        for(int col_i=i; col_i<N; col_i++){
            // 因爲這裏的U是從主元按照行的順序向後進行處理
            // 接下來便是求和的數據了, 求和是按照行向上進行的
            sum_val = 0.0;
            for(int d=i-1; d>=0; d--){
                // 內部的求和,必須是所操作行上面的所有行
                // sum_val += Arr[i][d]*Arr[d][col_i];
                sum_val += Arr[i*N+d] * Arr[d*N+col_i];
            }
            // Arr[i][col_i] -= sum_val;
            Arr[i*N+col_i] -= sum_val;
        }
        // 接下來我們該來處理L中對應的列上的元素了
        // 此處i將自動轉爲L中的列索引
        // 那麼下面我們首先應該去進行行的遍歷了
        for(int row_i=i+1; row_i<N; row_i++){
            // 接下來需要進行遍歷求和了,當然遍歷的是當前列的前面的所有列
            sum_val = 0.0;
            for(int col_i=i-1; col_i>=0; col_i--){
                // sum_val += Arr[row_i][col_i] * Arr[col_i][i];
                sum_val += Arr[row_i*N+col_i] * Arr[col_i*N+i];
            }
            // Arr[row_i][i] = (Arr[row_i][i] - sum_val) / Arr[i][i];
            Arr[row_i*N+i] = (Arr[row_i*N+i] - sum_val) / Arr[i*N+i];
         }
    }
}

運算結果見下圖:

程序有什麼問題,請留言,相互討論共同進步。千萬不要停下學習的腳步,社會競爭壓力很大。從學校出來以後,感覺錢真是太難掙了,尤其房價高的嚇人。估計等我攢夠買房子的錢的時候,我已經250歲了。

龍豬是個貧苦大戶,當前支持以下扶貧方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章