列主元高斯消去法解线性方程组——C语言实现

原理

高斯消去法

的基本原理就是用初等变换将用行的,逐次消去未知数的方法,把原来的方程组,化为与其等价的上三角方程组。
设有线性方程 A x = B \boldsymbol{A}\boldsymbol{x}=\boldsymbol{B} Ax=B,写成矩阵如下
[ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯ a m n ] [ x 1 x 2 ⋮ x n ] = [ b 1 b 2 ⋮ b n ] \left[ \begin{matrix} a_{11}& a_{12}& \cdots& a_{1n}\\ a_{21}& a_{22}& \cdots& a_{2n}\\ \vdots& \vdots& \ddots& \vdots\\ a_{m1}& a_{m2}& \cdots& a_{mn}\\ \end{matrix} \right]\left[ \begin{matrix} x_1\\ x_2\\ \vdots\\ x_n\\ \end{matrix} \right]= \left[ \begin{matrix} b_1\\ b_2\\ \vdots\\ b_n\\ \end{matrix} \right] a11a21am1a12a22am2a1na2namnx1x2xn=b1b2bn

该线性方程组的初始增广矩阵为

[ a 11 ( 0 ) a 12 ( 0 ) ⋯ a 1 n ( 0 ) b 1 ( 0 ) a 21 ( 0 ) a 22 ( 0 ) ⋯ a 2 n ( 0 ) b 2 ( 0 ) ⋮ ⋮ ⋱ ⋮ ⋮ a n 1 ( 0 ) a n 2 ( 0 ) ⋯ a m n ( 0 ) b n ( 0 ) ] \left[\begin{matrix} a_{11}^{(0)} & a_{12}^{(0)} & \cdots & a_{1 n}^{(0)} & b_{1}^{(0)} \\ a_{21}^{(0)} & a_{22}^{(0)} & \cdots & a_{2 n}^{(0)} & b_{2}^{(0)} \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ a_{n 1}^{(0)} & a_{n 2}^{(0)} & \cdots & a_{m n}^{(0)} & b_{n}^{(0)} \end{matrix}\right] a11(0)a21(0)an1(0)a12(0)a22(0)an2(0)a1n(0)a2n(0)amn(0)b1(0)b2(0)bn(0)
利用初等行变换的方法,即消元,将其化为如下形式

[ 1 a 12 ( n ) ⋯ a 1 n ( n ) b 1 ( n ) 0 1 ⋯ a 2 n ( n ) b 2 ( n ) ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 ⋯ 1 b n ( n ) ] \left[ \begin{matrix} 1& a_{12}^{\left( n \right)}& \cdots& a_{1n}^{\left( n \right)}& b_{1}^{\left( n \right)}\\ 0& 1& \cdots& a_{2n}^{\left( n \right)}& b_{2}^{\left( n \right)}\\ \vdots& \vdots& \ddots& \vdots& \vdots\\ 0& 0& \cdots& 1& b_{n}^{\left( n \right)}\\ \end{matrix} \right] 100a12(n)10a1n(n)a2n(n)1b1(n)b2(n)bn(n)
其上标 n n n表示进行第 n n n消元后的值

列主元高斯消去法

列主元高斯消去法较高斯消去法多了一步选取该列主元,即选取该列上绝对值最大的元素作为主元的步骤,交换该行与主元所在的行。目的是使得高斯消去法更稳定。举例说明,比如说现在有一个线性方程组 A x = B \boldsymbol{A}\boldsymbol{x}=\boldsymbol{B} Ax=B如下
2 x 1 − x 2 + 3 x 3 = 1 4 x 1 + 2 x 2 + 5 x 3 = 4 x 1 + 2 x 2 = 7 ​ \begin{array}{l} 2 x_{1}-x_{2}+3 x_{3}=1 \\ 4 x_{1}+2 x_{2}+5 x_{3}=4 \\ x_{1}+2 x_{2}=7 \end{array}​ 2x1x2+3x3=14x1+2x2+5x3=4x1+2x2=7
其增广矩阵为
[ 2 − 1 3 1 4 2 5 4 1 2 0 7 ] \left[\begin{matrix} 2&-1&3&1\\ 4&2&5&4\\ 1&2&0&7\\ \end{matrix}\right] 241122350147
在进行第一步消元时,先选取第一列中绝对值最大的元素4作为主元,交换第一行和第二行,得到
[ 4 2 5 4 2 − 1 3 1 1 2 0 7 ] \left[\begin{matrix} 4&2&5&4\\ 2&-1&3&1\\ 1&2&0&7\\ \end{matrix}\right] 421212530417
再进行消元,得到
[ 4 2 5 4 0 − 2 0.5 − 3 0 1.5 − 1.25 6 ] \left[\begin{matrix} 4&2&5&4\\ 0&-2&0.5&-3\\ 0&1.5&-1.25&6\\ \end{matrix}\right] 400221.550.51.25436

算法

  1. ∃ l ∈ { k , k + 1 , … , n } a l k = max ⁡ k ≤ i ≤ n a i k , a l j ⇔ a k j , j = k , k + 1 , … , n \exists l \in \{k,k+1,\ldots,n\}\\a_{lk}=\max\limits_{k\le i \le n}a_{ik},a_{lj}\Leftrightarrow a_{kj},j=k,k+1,\ldots,n l{k,k+1,,n}alk=kinmaxaik,aljakj,j=k,k+1,,n

  2. a k j ( k ) = a k j ( k − 1 ) / a k k ( k − 1 ) a i j ( k ) = a i j ( k − 1 ) − a i k ( k − 1 ) a k j ( k ) , i , j = k , k + 1 , … , n a_{k j}^{(k)}=a_{k j}^{(k-1)} / a_{k k}^{(k-1)}\\a_{i j}^{(k)}=a_{i j}^{(k-1)}-a_{i k}^{(k-1)} a_{k j}^{(k)},i,j=k,k+1,\ldots,n akj(k)=akj(k1)/akk(k1)aij(k)=aij(k1)aik(k1)akj(k),i,j=k,k+1,,n

  3. x n = a n , n + 1 ( n ) , i = n x i = a i , n + 1 ( n ) − ∑ j = i + 1 n a i j ( n ) x j , i = n − 1 , n − 2 , ⋯   , 1 \begin{array}{l} x_{n}=a_{n, n+1}^{(n)},i=n \\ x_{i}=a_{i, n+1}^{(n)}-\sum_{j=i+1}^{n} a_{i j}^{(n)} x_{j},i=n-1, n-2, \cdots, 1 \\ \end{array} xn=an,n+1(n),i=nxi=ai,n+1(n)j=i+1naij(n)xj,i=n1,n2,,1

c程序

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void gauss(double[], double[], double[], int);

int main(int argc, char* argv[])
{
    int n           = 4;
    double a[4 * 4] = { 1, 1, 0, 3,
                        2, 1, -1, 1,
                        3, -1, -1, 3,
                        -1, 2, 3, -1 };
    double b[4]     = { 4, 1, -3, 4 };
    double x[4]     = {};

    printf("增广矩阵\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%f\t", a[i * n + j]);
        }
        printf("%f\n", b[i]);
    }
    printf("解向量\n");
    gauss(a, b, x, n);
    for (int i = 0; i < n; i++)
        printf("%f\t", x[i]);
    printf("\n");
    return 0;
}

void gauss(double a[], double b[], double x[], int n)//列主元高斯消去法,a[]系数矩阵,b[]结果向量,x[]解向量,n阶数
{
    int i, j, k, exchangeline, exchangeflag = 0;
    double temp, max;

    for (k = 0; k < n - 1; k++) { //k迭代次数
        max = a[k * n + k];
        for (i = k + 1; i < n; i++) { //寻找主元,i行号
            if (fabs(max) < fabs(a[n * i + k])) {
                max          = a[n * i + k];
                exchangeflag = 1;     //交换标志
                exchangeline = n * i; //记录需要交换的行号
            }
        }
        if (exchangeflag) { //换行,j列号
            for (j = 0; j < n; j++) {
                temp                = a[exchangeline + j]; //对系数矩阵操作
                a[exchangeline + j] = a[k * n + j];
                a[k * n + j]        = temp;
            }
            temp                = b[exchangeline / n]; //对结果向量操作
            b[exchangeline / n] = b[k];
            b[k]                = temp;
            exchangeflag        = 0; //清除交换标志
        }
        for (i = k + 1; i < n; i++) { //消元
            temp = a[i * n + k] / a[k * n + k];
            b[i] = b[i] - b[k] * temp; //对结果向量操作
            for (j = k; j < n; j++)
                a[i * n + j] = a[i * n + j] - a[k * n + j] * temp; //对系数矩阵操作
        }
    }
    for (i = n - 1; i > -1; i--) { //回代
        temp = b[i];
        for (j = n - 1; j > i; j--)
            temp = temp - a[n * i + j] * x[j];
        x[i] = temp / a[i * n + i];
    }
}

运行结果

在这里插入图片描述

  • 16
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,我来给您讲一下。 首先,列主元高斯消去法是一种线性方程组的方法,其基本思路是将系数矩阵通过一系列的初等变换,转化为上三角矩阵,然后再通过回代求得到方程组C语言实现列主元高斯消去法的步骤如下: 1. 定义系数矩阵A和右端向量b,以及n个未知数的向量x。 2. 将A和b合并成增广矩阵Ab。 3. 从第一行开始,每次选取当前行及其以下所有行中绝对值最大的元素作为主元素,并将其所在的行与当前行交换位置。 4. 对于每一行i,将第i列以下的所有元素消为0,即用第i行乘以一个系数k,加到第i+1行至第n行上。 5. 得到上三角矩阵后,通过回代求x。 以下是C语言代码实现: ```c #include <stdio.h> #include <math.h> #define N 3 // 未知数个数 int main() { int i, j, k; double A[N][N+1], x[N], L[N][N], U[N][N]; double temp, max, pivot; // 输入系数矩阵A和右端向量b printf("请输入系数矩阵A和右端向量b:\n"); for(i=0; i<N; i++) { for(j=0; j<N+1; j++) { scanf("%lf", &A[i][j]); } } // 初始化L和U for(i=0; i<N; i++) { for(j=0; j<N; j++) { if(i == j) { L[i][j] = 1.0; } else { L[i][j] = 0.0; } U[i][j] = 0.0; } } // 列主元高斯消去 for(k=0; k<N-1; k++) { // 选取主元 max = 0; for(i=k; i<N; i++) { if(fabs(A[i][k]) > max) { max = fabs(A[i][k]); pivot = A[i][k]; j = i; } } if(max == 0) { printf("主元为0,无唯一!\n"); return 1; } // 交换行 if(j != k) { for(i=0; i<N+1; i++) { temp = A[k][i]; A[k][i] = A[j][i]; A[j][i] = temp; } } // 消元 for(i=k+1; i<N; i++) { temp = A[i][k] / pivot; L[i][k] = temp; for(j=k; j<N+1; j++) { A[i][j] = A[i][j] - temp * A[k][j]; } } } // 输出上三角矩阵U printf("上三角矩阵U:\n"); for(i=0; i<N; i++) { for(j=0; j<N; j++) { printf("%8.3lf ", A[i][j]); U[i][j] = A[i][j]; } printf("\n"); } // 输出下三角矩阵L printf("下三角矩阵L:\n"); for(i=0; i<N; i++) { for(j=0; j<N; j++) { if(i > j) { printf("%8.3lf ", L[i][j]); } else { printf("%8.3lf ", 0.0); } } printf("\n"); } // 回代求x x[N-1] = A[N-1][N] / A[N-1][N-1]; for(i=N-2; i>=0; i--) { temp = 0; for(j=i+1; j<N; j++) { temp += A[i][j] * x[j]; } x[i] = (A[i][N] - temp) / A[i][i]; } // 输出向量x printf("方程组向量x:\n"); for(i=0; i<N; i++) { printf("%8.3lf ", x[i]); } printf("\n"); return 0; } ``` 希望能对您有所帮助!
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值