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

题目描述:

给定一个线性方程组,对其求解
输入格式:第一行,一个正整数n第二至n+1行,每行n+1个整数,为a1,a2…am和b,代表一组方程
输出格式:共n行,每行一个数,第i行为xi(保留2位小数)如果不存在唯一解,在第一行输出”No Solution”.
输入样例#1:
3
1 3 4 5
1 4 7 3
9 3 2 2
输出样例#1:
-0.97
5.18
-2.39
说明:1<=n<=100,|ai|<=10^ 4,|b|<=10^4。

高斯消元法详解:

[这位讲的比较详细:大家可以看一看]
http://t.csdn.cn/mOYlz

伪代码

第一步:两个for 循环输入每行系数以及常数。再加一个for循环验证是否有唯一解(当任意一个第i行第i列元素为0时,有无穷个解)。若没有唯一解,则输出“No Solution”结束计算,否则,进入第二步。
第二步:从第 i ( i 为未知量的个数)个系数开始,依次对后面行的第i个系数进行消元(两行元素互相乘另一行第i 个元素的值并进行相减)。使得每行(举例为第i行)的第i个元素之前都为0。再加一个for循环验证是否有唯一解(当任意一个第i行第i列元素为0时,有无穷个解)。若没有唯一解,则输出“No Solution”结束计算,否则,进入第三步。
第三步:从二维数组最后一行算起,第i个未知量的值都等于每行最后一个常数减去这个未知量后面所有想的值,再除这一项的系数(a[i][i])。进入第四步。
第四步:输出所有未知量的解。

代码实现

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

float MIN=1e-8;
float ans[100];
int a[100][101];//系数以及常数的数组a[1][1]*X1+a[1][2]*X2+...+a[1][n]*Xn=a[1][n+1] 

int  isUniqueAns(int a[100][101],int i);
int  init(int a[100][101],int i,int j);
void printfResult(float ans[100],int i);
void getResult(int a[100][101],float ans[100],int i);
void mul(int num,int a[101],int j);
void offset(int a[101],int b[100],int i,int j);
int  Guss(int a[100][101],int i,int j);

int main(){
	int numberOfUnknown;//未知量的数量 
	printf("请输入线性方程组未知数数量:");
	scanf("%d",&numberOfUnknown);
	int init_f=init(a,numberOfUnknown,numberOfUnknown+1);
	if(init_f==0){
		return 0;
	}
	int Guss_f=Guss(a,numberOfUnknown,numberOfUnknown+1);
	if(Guss_f==0){
		return 0;
	}
	return 0;
}

int isUniqueAns(int a[100][101],int i){
	for(int m=1;m<=i;m++){
		if(abs(a[m][m])<MIN){
			printf("No Solution");
			return 0;
		}
	}
	return 1;
}

int init(int a[100][101],int i,int j){//输入所有的系数和常数 
	for(int m=1;m<=i;m++){
		printf("请输入第%d行系数与常数:",m);
		for(int n=1;n<=j;n++){
			scanf("%d",&a[m][n]);
		}
	}
	if(isUniqueAns(a,i)==0){
		return 0;
	}
	return 1;
}

void printfResult(float ans[100],int i){//结果输出 
	for(int m=1;m<i;m++){
		printf("%.2f\n",ans[m]);
	}
	printf("%.2f",ans[i]);
}

void getResult(int a[100][101],float ans[100],int i){
	for(int m=i;m>=1;m--){//从最后一行开始向前算出每个未知数的值 
		float sum=0;//初始值为第m行的常数 
		for(int n=i+1;n>m;n--){//第m行其他数换为常数 
			sum+=a[m][n]*ans[n];
		}
		ans[m]=(a[m][i+1]-sum)/a[m][m];//结合系数进行计算 
	}
	printfResult(ans,i);
}

void mul(int num,int a[101],int j){//将一个一维数组进行乘某个整数的变换 
	for(int m=1;m<=j;m++){
		a[m]=num*a[m];
	}
}

void offset(int a[101],int b[101],int i,int j){//两个一维数组相减,前者减去后者的变换 
	for(int m=i;m<=j;m++){
		a[m]=a[m]-b[m];
	}
}

int Guss(int a[100][101],int i,int j){//高斯消元法 
	for(int m=1;m<i;m++){//第m行,表示第m个未知数的消元 
		for(int n=m+1;n<=i;n++){//第m+1行,表示要进行变换的那一行 
			//将两行的数字进行乘
			mul(a[m][m],a[n],j);
			mul(a[n][m],a[m],j);
			//两行抵消
			offset(a[n],a[m],m,j);
		} 
	}
	
	if(isUniqueAns(a,i)==0){//再次判断是否有解 
		return 0;
	}
	getResult(a,ans,i);
	
	return 1;
}

运行结果截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码分析

时间复杂度:O(n^3)
空间复杂度:O(1)
[时间复杂度和空间复杂度的详解请看这位大神]
http://t.csdn.cn/59zHc

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值