2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 解线性方程组的直接方法:LU分解法及其C语言算法实现

解线性方程组的直接方法:LU分解法及其C语言算法实现

时间:2019-03-03 12:17:06

相关推荐

解线性方程组的直接方法:LU分解法及其C语言算法实现

在上一篇博客里面,笔者介绍了解线性方程组的列主元Guass消元法,这篇将介绍LU分解法及其算法实现.

什么是LU分解?

对于一个线性方程组Ax=b,其中A是非奇异系数矩阵,b是线性方程组右端项,在列主元Guass消元法里面我们知道,最后的系数矩阵A将变成一个上三角矩阵,并且是通过一系列的行变换而来的,设最后得到的上三角矩阵为U,结合高等代数的知识,一个矩阵左乘一个初等矩阵,相当于进行一次行变换,因此设每一次A左乘的初等矩阵为Li(i=1,2,…,n),则有LnL(n-1)…L1A=U,由于Ln均为初等矩阵,且均为下三角单位矩阵(因为每次A进行消元所做的行变换均是从上面的行消去下面的行),所以设L=LnL(n-1)*…*L1,LA=U,A=L-1U,L-1也为单位下三角矩阵,然后得到了A=LU,我们可以设Ux=y,Ly=b,由于L为下三角矩阵,求解难度较小,因此通过求解y向量,再由Ux=y求解x,这便是LU分解全部步骤了,对于LU分解矩阵的详细计算过程,大家可以参考这个网站link

接下来话不多说,上代码

初始化矩阵

double** init_Matrix(int r, int c){double** p = new double* [r];int d = c + 1;for (int i = 0; i < r; i++){p[i] = new double[d];memset(p[i], 0, sizeof(double) * d);}cout << "请输入线性方程组对应的增广矩阵:" << endl;for (int i = 0; i < r; i++){for (int j = 0; j < d; j++){cin >> p[i][j];}}return p;}

进行LU分解

void LU_Position(double**a,int r ,int c){double num1 = 0,num2=0;for (int i=0;i<r;i++){if (i==0)//第一行不做处理,单独算第一列{for (int j = 1; j < c; j++){a[j][i] = a[j][i] / a[0][0];}}else{for (int j = i; j < c; j++){num1 = 0;for (int k = 0; k < i; k++){num1 += a[i][k] * a[k][j];}a[i][j] = a[i][j] - num1;}for (int j = i+1; j < r; j++){num2 = 0;for (int k = 0; k < i; k++){num2 += a[j][k] * a[k][i];}a[j][i] = (a[j][i] - num2) / a[i][i];}}}cout << "所得的LU矩阵为:" << endl;for (int k = 0; k < r; k++){for (int n = 0; n < c; n++){printf("%f\t", a[k][n]);}cout << endl;}}

注意:此时我们得到了LU,由于这两个矩阵均为稀疏矩阵,且拼接后大小与A矩阵相同,因此我们一直接将计算的两个矩阵储存在A矩阵中(A中最后一列为右端项,不进行处理),这部分计算大家特别要注意的是数组的行列下边关系

计算y向量及x向量

void calculate(double*y, double*x, double**a,int r){y[0] = a[0][r];double sum=0;for (int i = 1; i < r; i++){sum = 0;for (int k = 0; k < i; k++){sum += a[i][k] * y[k];}y[i] = a[i][r] - sum;}cout << "所求的向量Y为:" << endl;for (int i = 0; i < r; i++){printf("%f\t", y[i]);}cout << endl;for (int i = r-1; i >=0; i--){sum = 0;for (int j=i+1;j<r;j++){sum += a[i][j] * x[j];}x[i] = (y[i] - sum) / a[i][i];}cout << "所求线性方程组的解向量X为:" << endl;for (int i = 0; i < r; i++){printf("%f\t", x[i]);}cout << endl;}

这里我们将得到的y向量储存在数组y中

程序完整代码

#include<iostream>#include<Windows.h>using namespace std;/*测试数据2 22 3 51 -1 03 33 2 -3 -21 1 1 61 2 -1 23 31 2 -3 12 -1 3 53 -2 2 14 44 -3 6 7 111 1 3 4 10-2 9 -7 1 103 3 -4 20 255 528 -3 0 0 0 10-3 38 -10 0 -5 00 -10 25 -15 0 00 0 -15 45 0 00 -5 0 0 30 0*/double** init_Matrix(int r, int c){double** p = new double* [r];int d = c + 1;for (int i = 0; i < r; i++){p[i] = new double[d];memset(p[i], 0, sizeof(double) * d);}cout << "请输入线性方程组对应的增广矩阵:" << endl;for (int i = 0; i < r; i++){for (int j = 0; j < d; j++){cin >> p[i][j];}}return p;}//直接用A来储存LU和方程组右边的常数项 进行LU分解时 右边常数项不做处理 即最后一列全部不处理void LU_Position(double**a,int r ,int c){double num1 = 0,num2=0;for (int i=0;i<r;i++){if (i==0){for (int j = 1; j < c; j++){a[j][i] = a[j][i] / a[0][0];}}else{for (int j = i; j < c; j++){num1 = 0;for (int k = 0; k < i; k++){num1 += a[i][k] * a[k][j];}a[i][j] = a[i][j] - num1;}for (int j = i+1; j < r; j++){num2 = 0;for (int k = 0; k < i; k++){num2 += a[j][k] * a[k][i];}a[j][i] = (a[j][i] - num2) / a[i][i];}}}cout << "所得的LU矩阵为:" << endl;for (int k = 0; k < r; k++){for (int n = 0; n < c; n++){printf("%f\t", a[k][n]);}cout << endl;}}void calculate(double*y, double*x, double**a,int r){y[0] = a[0][r];double sum=0;for (int i = 1; i < r; i++){sum = 0;for (int k = 0; k < i; k++){sum += a[i][k] * y[k];}y[i] = a[i][r] - sum;}cout << "所求的向量Y为:" << endl;for (int i = 0; i < r; i++){printf("%f\t", y[i]);}cout << endl;for (int i = r-1; i >=0; i--){sum = 0;for (int j=i+1;j<r;j++){sum += a[i][j] * x[j];}x[i] = (y[i] - sum) / a[i][i];}cout << "所求线性方程组的解向量X为:" << endl;for (int i = 0; i < r; i++){printf("%f\t", x[i]);}cout << endl;}void LU_position_main() {cout << "输入矩阵的行列:" << endl;int i = 0, j = 0;cin >> i >> j;double** p = init_Matrix(i, j);LU_Position(p, i, j);double* a = new double[i];memset(a, 0, sizeof(double) * i);double* b = new double[i];memset(b, 0, sizeof(double) * i);calculate(a, b, p, i);delete[]a;delete[]b;for (int i = 0; i < j; i++){delete[]p[i];}delete[]p;}int main(void) {LU_position_main();system("pause");return 0;}

欢迎交流探讨~~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。