高斯消元法解线性方程组和矩阵求逆(C++面向对象实现)

本文介绍了如何使用C++面向对象编程实现高斯消元法,详细阐述了Vector向量类、Matrix矩阵类的设计,并通过MatrixVector和MatrixMatrix类处理向量和矩阵的运算。该实现涵盖了线性方程组的求解和矩阵的求逆功能。
摘要由CSDN通过智能技术生成

在这里插入图片描述

实现了两个向量和矩阵的基本类,针对处理对象创建了MatrixVector类和MatrixMatrix类。使用gauss法同时实现了线性方程组的求解和矩阵的求逆

0. 预处理

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;

//
double DoubleRnd(){
	return rand() / 32767.0; // RAND_MAX = (int)32767 , 此处表示0-1的随机小数 
}
//

1. Vector向量类

class Vector{
private:
	int nDim;
	double* Vect;
public:
	Vector(int nDim);
	Vector(Vector& v);
	~Vector() { delete[] Vect;}
	void Set(int nX, double r) { Vect[MakeIndex(nX)] = r;}
	double Get(int nX) { return Vect[MakeIndex(nX)]; }
	int GetDim() {return nDim;}
private:
	void InitMemory() { Vect = new double[nDim];}
	int MakeIndex(int nX) { return nX - 1;	}
	void Set0(int nX) { Set(nX, 0);	}
public:
	void InitNul();
	void InitRnd();
	friend ostream& operator<<(ostream& os, Vector& v);
	///高斯求解所需函数
	void Divid(double R, int nVerh);
	void Minus(double R, int nNizz, int nVerh); 
};

Vector::Vector(int nDim){
	this->nDim = nDim;
	InitMemory();
}

Vector::Vector(Vector& v){
	nDim = v.nDim;
	InitMemory();
	for(int i = 1; i <= nDim; i++)
		Set(i, v.Get(i));
}

void Vector::InitNul(){
	for(int i =1; i <= nDim; i++) Set0(i);
} 

void Vector::InitRnd(){
	for(int i =1; i <= nDim; i++) Set(i, DoubleRnd());
} 

void Vector::Divid(double R, int nVerh){
	Set(nVerh, Get(nVerh) / R);
}

void Vector::Minus(double R, int nNizz, int nVerh){
	Set(nNizz, Get(nNizz)-R*Get(nVerh));
}

ostream& operator<<(ostream& os, Vector& v){ 
	for(int j = 1; j <= v.nDim; j++){
		os.width(10);
		os.precision(3);
		os << v.Get(j) << " ";
	}
	return os;
}

2. Matrix矩阵类

class Matrix{
private:
        int nDim;
        double* Matr; 
public:
        Matrix(int nDim); 
        Matrix(Matrix& m); 
        ~Matrix(){delete[] Matr;}
        void Set(int nX, int nY, double r) {Matr[MakeIndex(nX, nY)] = r;} 
        double Get(int nX, int nY) {return Matr[MakeIndex(nX, nY)]; } 
        int GetDim(){return nDim;}
private:
        void InitMemory(){ Matr = new double[nDim * nDim]; } 
        int MakeIndex(int nX, int nY){return (nX - 1) * nDim + (nY - 1);} 
        void Set0(int nX, int nY) { Set(nX,nY,0);} 
        void Set1(int nX, int nY) { Set(nX,nY,1);} 
public:
        void InitNul();
        void InitOne();
        void InitRnd();
        friend ostream& operator<<(ostream& os, Matrix& m);
        void Divid(double R, int nVerh); // 将每一行除以其对应的对角线元素
        void Minus(double R, int nNizz, int nVerh); 

};

implementation
Matrix::Matrix(int nDim){
	this->nDim = nDim;
	InitMemory();
} 

Matrix::Matrix(Matrix& m){
	nDim = m.nDim;
	InitMemory();
	for(int i = 1; i<=nDim; i++)
		for(int j = 1; j<=nDim; j++)
			Set(i, j, m.Get(i, j));
}

void Matrix::InitNul(){   
	for(int i = 1; i <= nDim; i++)
		for(int j = 1; j <= nDim; j++)
			Set0(i, j);
}

void Matrix::InitOne(){  
	for(int i = 1; i <= nDim; i++)
		for(int j = 1; j <= nDim; j++){
			Set0(i, j);
			if(i != j) continue;
			Set1(i, j); 
		}
			
}

void Matrix::InitRnd(){  
	for(int i = 1; i <= nDim; i++)
		for(int j = 1; j <= nDim; j++)
			Set(i, j, DoubleRnd());
}

ostream& operator<<(ostream& os, Matrix& m){
	os << m.nDim << endl;
	for(int i = 1; i <= m.nDim; i++){
		for(int j = 1; j <= m.nDim; j++){
			os.width(10);
			os.precision(3);
			os << m.Get(i, j) << " ";
		}
		os << endl;
	}
	return os;
}

void Matrix::Divid(double R, int nVerh){
	for (int j = 1; j <= nDim; j++)
		Set(nVerh, j, Get(nVerh, j)/R);
}

void Matrix::Minus(double R, int nNizz, int nVerh){
	for (int j = 1; j <= nDim; j++)
		Set(nNizz, j, Get(nNizz, j)-R*Get(nVerh, j));
}

3. MatrixVector类

class MatrixVector{ //系数矩阵Matrix + 常数向量 Vector = MatrixVector类:用于求解线性方程组
private:
	int nDim;
	Matrix MMM;
	Vector VVV;
public:
	MatrixVector(int nDim);
	void InitRnd();
	void InitMatrix(Matrix& M);
	void InitVector(Vector& V);
	Vector& GetVector(){ return VVV; }
	friend ostream& operator<<(ostream& os, MatrixVector& mv);
	//以下为高斯求解所需的函数
	void Divid(double R, int nVerh){ MMM.Divid(R, nVerh); VVV.Divid(R, nVerh);}	 // 除法,矩阵除以向量VVV
	void Minus(double R, int nNizz, int nVerh) {MMM.Minus(R, nNizz, nVerh); VVV.Minus(R, nNizz, nVerh);} // 减法,矩阵减去向量VVV
	void Tuda();
	void Obratno();
}; 

implementation
MatrixVector::MatrixVector(int nDim) : MMM(nDim), VVV(nDim){ //初始化列表:等同于Matrix MMM(int nDim);Vector VVV(int nDim); 
	this->nDim = nDim;
} 

void MatrixVector::InitRnd(){
	MMM.InitRnd();
	VVV.InitRnd();
}

void MatrixVector::InitMatrix(Matrix& M){
	for(int i = 1; i <= nDim; i++)
		for(int j = 1; j <= nDim; j++)
			M.Set(i, j, MMM.Get(i, j));
}

void MatrixVector::InitVector(Vector& V){
	for(int i = 1; i <= nDim; i++)
		V.Set(i, VVV.Get(i)); 
}

ostream& operator<<(ostream& os, MatrixVector& mv){
	os << mv.nDim << endl;
	for(int i = 1; i <= mv.nDim; i++){
		for(int j = 1 ; j <= mv.nDim; j++){
			os.width(10);
			os.precision(3);
			os << mv.MMM.Get(i, j) << " "; 
		}
		os.width(14);
		os.precision(3);
		os << mv.VVV.Get(i) << " ";
		os << endl;
	}
	return os;
}


void MatrixVector::Tuda(){  // 直接高斯 
	for(int i = 1; i <= nDim; i++){
		Divid(MMM.Get(i, i), i);
		for(int j =i + 1; j <= nDim; j++) 
			Minus(MMM.Get(j, i), j, i);
	}
} 


void MatrixVector::Obratno(){ // 相反方向(从右到左从下至上)再化简一次矩阵(由上三角转为单位矩阵)   O(n^3) Matrix::Minus中还有一重for循环,可以修改为O(n^2) 但是影响代码耦合度
	for(int i = nDim; i >= 2; i--)
		for(int j = i - 1; j >= 1; j--)
			Minus(MMM.Get(j, i), j, i);
} 

///
void Multi(Matrix& MMM, Vector& VVV, Vector& VVVotv){
	int nDim = MMM.GetDim();
	for(int i = 1; i <= nDim; i++){
		double R = 0;
		for(int j = 1; j <= nDim; j++)
			R += MMM.Get(i, j) * VVV.Get(j);
		VVVotv.Set(i, R);   
	}
}

double Nevya(Vector& VVV1, Vector& VVV2){
	int nDim = VVV1.GetDim();
	double R = 0;
	for(int i = 1; i <= nDim; i++) R += pow(VVV1.Get(i) - VVV2.Get(i), 2);
	return pow(R, 0.5); 
}

4. MatrixMatrix类


class MatrixMatrix{  //系数矩阵Matrix + 单位矩阵Matrix = MatrixMatrix类:用于求逆矩阵
private:
	int nDim;
	Matrix MMM;
	Matrix VVV;
public:
	MatrixMatrix(int nDim);
	void InitRnd();
	void InitMatrix(Matrix& M);
	Matrix& GetMatrix() {return VVV;}
	friend ostream& operator<<(ostream& os, MatrixMatrix& mv);
	//以下为高斯求逆矩阵所需的函数
	void Divid(double R, int nVerh){ MMM.Divid(R, nVerh); VVV.Divid(R, nVerh);}	
	void Minus(double R, int nNizz, int nVerh) {MMM.Minus(R, nNizz, nVerh); VVV.Minus(R, nNizz, nVerh);}
	void Tuda();
	void Obratno();
}; 

implementation
MatrixMatrix::MatrixMatrix(int nDim) : MMM(nDim), VVV(nDim){ //初始化列表:等同于Matrix MMM(int nDim); Matrix VVV(int nDim); 
	this->nDim = nDim;
} 

void MatrixMatrix::InitRnd(){
	MMM.InitRnd();
	VVV.InitOne(); // 注意这里初始化为单位矩阵 
}

void MatrixMatrix::InitMatrix(Matrix& M){
	for(int i = 1; i <= nDim; i++)
		for(int j = 1; j <= nDim; j++)
			M.Set(i, j, MMM.Get(i, j));
}


ostream& operator<<(ostream& os, MatrixMatrix& mv){
	os << mv.nDim << endl;
	for(int i = 1; i <= mv.nDim; i++){
		for(int j = 1 ; j <= mv.nDim; j++){
			os.width(10);
			os.precision(3);
			os << mv.MMM.Get(i, j) << " "; 
		}
		os << "      ";
		for(int j = 1; j <= mv.nDim; j++){
			os.width(10);
			os.precision(3);
			os << mv.VVV.Get(i, j) << " ";
		}
		os << endl;
	}
	return os;
}


void MatrixMatrix::Tuda(){
	for(int i = 1; i <= nDim; i++){
		Divid(MMM.Get(i, i), i);
		for(int j =i + 1; j <= nDim; j++) 
			Minus(MMM.Get(j, i), j, i);
	}
} 


void MatrixMatrix::Obratno(){ // O(n^3) - Matrix::Minus中还有一重for循环 ,不能改为O(n^2) 
	for(int i = nDim; i >= 2; i--)
		for(int j = i - 1; j >= 1; j--)
			Minus(MMM.Get(j, i), j, i);
} 

///
void Multi(Matrix& MMM, Matrix& VVV, Matrix& VVVotv){ // 矩阵乘法 
	int nDim = MMM.GetDim();
	for(int i = 1; i <= nDim; i++)
		for(int j = 1; j <= nDim; j++){
		double R = 0;
		for(int k = 1; k <= nDim; k++)
			R += MMM.Get(i, k) * VVV.Get(k, j);
		VVVotv.Set(i, j, R);   
	}
}

double Nevya(Matrix& VVV1, Matrix& VVV2){ // 误差 
	int nDim = VVV1.GetDim();
	double R = 0;
	for(int i = 1; i <= nDim; i++) for(int j = 1; j <= nDim; j++)R += pow(VVV1.Get(i, j) - VVV2.Get(i, j), 2);
	return pow(R, 0.5); 
}


5. 运行调用

int main(int argc, char** argv){ 
	srand(time(NULL)); // 表示设置一个随机种子,每次运行都能保证随机种子不同。(因为rand会默认取上一次随机出来的结果,达不到每次调用都随机的效果)
	int nDim = 4; 
	
	//
	MatrixVector MV(nDim);  MV.InitRnd(); cout << MV << endl;
	Matrix M(nDim); MV.InitMatrix(M);
	Vector V(nDim); MV.InitVector(V);
	MV.Tuda(); MV.Obratno(); cout << MV << endl;
	Vector VV(nDim);
	Multi(M, MV.GetVector(), VV); cout << VV<< endl << endl;
	
	cout << Nevya(VV, V) << endl;
	//
	cout << endl << endl<< endl<< endl<< endl<< endl<< endl<< endl;
	//
	MatrixMatrix MM(nDim);  MM.InitRnd(); cout << MM << endl;
	MM.InitMatrix(M);
	Matrix VM(nDim);
	MM.Tuda(); MM.Obratno(); cout << MM << endl;
	Matrix VVM(nDim);
	Multi(M, MM.GetMatrix() , VVM); cout << VVM << endl;
	cout << Nevya(VVM, VM) << endl;
	//
	
	return 0;
}

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值