1. 程式人生 > >高斯消去法解線性方程組C++實現

高斯消去法解線性方程組C++實現

       一.問題分析:高斯消去法解線性方程組主要面對的問題是矩陣的運算,所以可以定義一個矩陣類Matrix類作為基類,然後由矩陣類Matrix類派生出一個線性方程組類LinearEqu類。

       二.矩陣功能分析:(1)Matrix類處理n*n的方陣,方陣用一個一維陣列存放,矩陣類Matrix的資料成員包括陣列的首地址和矩陣長度n,函式成員有設定矩陣的值setMatrix()和顯示矩陣printMatrix()。(2)LinearEqu類除了由矩陣Matrix繼承過來的存放矩陣A的成員之外,還包括存放解向量X

和方程右端向量b的陣列的首地址。LinearEqu類的主要操作有方程組設定setLinearEqu(),顯示printLinearEqu(),求解solve()及輸出方程組的解printSolution()

注:Matrix類只對矩陣進行處理,不摻雜任何方程思想,LinearEqu類利用矩陣類來求解方程

       三.畫出UML圖

                          

         四.程式碼

             Matrix.h檔案

#ifndef _MATRIX_H_
#define _MATRIX_H_
class Matrix{
public:
	Matrix(int size = 2);
	~Matrix();
	void setMatrix(const double* values);//矩陣賦初值
	void printMatrix() const;//顯示矩陣
	int getSize() const{ return size; }//得到矩陣大小
	double &element(int i, int j){ return elements[i*size + j]; }
	double element(int i, int j) const{ return elements[i*size + j]; }//取矩陣的第i行第j列的元素
private:
	int size;
	double* elements;//矩陣存放陣列首地址
};
#endif

 Matrix.cpp檔案,實現Matrix.h中宣告的函式 

#include"Matrix.h"
#include<iostream>
using namespace std;

Matrix::Matrix(int size /*= 2*/) :size(size){//Matrix類的建構函式的實現
	elements = new double[size*size];//動態記憶體分配
}

Matrix::~Matrix(){//矩陣Matrix的解構函式
	delete[] elements;//記憶體釋放
}

void Matrix::setMatrix(const double* values){//矩陣賦初值
	for (int i = 0; i < size*size; i++)
		elements[i] = values[i];
}

void Matrix::printMatrix() const{//顯示矩陣
	cout << "The Matrix is:" << endl;
	for (int i = 0; i < size; i++){
		for (int j = 0; j < size; j++)
			cout << element(i, j) << " ";
		cout << endl;
	}
}

 LinearEqu.h檔案

#ifndef _LINEAREQU_H_
#define _LINEAREQU_H_
#include"Matrix.h"
class LinearEqu :public Matrix{
public:
	LinearEqu(int size = 2);
	~LinearEqu();
	void setLinearEqu(const double* a, const double* b);//方程賦值(設定線性方程組)
	//a表示的是係數矩陣,b表示的是右端矩陣
	bool solve();//全選主元高斯消去法求解方程
	void printLinearEqu() const;//顯示方程
	void printSolution() const;//顯示方程的解
private:
	double* sums;//方程右端向量
	double* solution;//方程的解
};
#endif

 LinearEqu.cpp檔案,實現LinearEqu.h中宣告的函式 

#include"LinearEqu.h"
#include<iostream>
#include<cmath>
using namespace std;

//用size呼叫基類建構函式
LinearEqu::LinearEqu(int size/*=2*/) :Matrix(size) {
	sums = new double[size];//動態記憶體分配
	solution = new double[size];
}

LinearEqu::~LinearEqu(){
	delete[] sums;
	delete[] solution;
}

//設定線性方程組
void LinearEqu::setLinearEqu(const double* a, const double* b){
	setMatrix(a);//呼叫基類函式
	for (int i = 0; i < getSize(); i++)
		sums[i] = b[i];
}

//顯示線性方程組
void LinearEqu::printLinearEqu() const{
	cout << "The Line eqution is:" << endl;
	for (int i = 0; i < getSize(); i++){
		for (int j = 0; j < getSize(); j++)
			cout << element(i, j) << " ";
		cout << "     " << sums[i] << endl;
	}
	cout << endl;
}

//輸出方程的解
void LinearEqu::printSolution() const{
	cout << "The Result eqution is:" << endl;
	for (int i = 0; i < getSize(); i++)
		cout << "x[" << i << "]=" << solution[i] << endl;
}

//交換兩個實數
inline void swap(double &v1, double &v2){
	double temp = v1;
	v1 = v2;
	v2 = temp;
}

bool LinearEqu::solve(){//全選主元素高斯消去法求解方程
	int *js = new int[getSize()];//儲存主元素所在列號的陣列

	//選主元素
	for (int k = 0; k < getSize()-1; k++){
		int is;//主元素所在行號
		double max = 0;//所有元素的最大值
		for (int i = k; i < getSize(); i++){
			for (int j = k; j < getSize(); j++){
				double t = fabs(element(i, j));
				if (t > max){
					max = t;
					js[k] = j;
					is = i;
				}
			}
		}
		if (max == 0){
			delete[] js;
			return false;
		}
		else{
			//通過行列交換,把主元素交換到第k行第k列上
			if (js[k] != k)//主元素不在第k列上,交換一列
				for (int i = 0; i < getSize(); i++)
					swap(element(i, k), element(i, js[k]));
			if (is != k){//主元素不在第k行上,交換一行
				for (int j = k; j < getSize(); j++){
					swap(element(is, j), element(k, j));
					swap(sums[k], sums[is]);
				}
			}
		}

		//消去過程
		double major = element(k, k);
		for (int j = k + 1; j < getSize(); j++)
			element(k, j) /= major;
		sums[k] /= major;
		for (int i = k + 1; i < getSize(); i++){
			for (int j = k + 1; j < getSize(); j++)
				element(i, j) -= element(i, k)*element(k, j);//行之間的操作
			sums[i] -= element(i, k)*sums[k];
		}
	}
	//判斷剩下的一個元素是否等於0(等於0則矩陣的秩不等於矩陣的行數,則無解)
	double d = element(getSize() - 1, getSize() - 1);
	if (fabs(d) < 1e-15){
		delete[] js;
		return false;
	}

	//求出解之前驗證一下最終化簡結果
	printMatrix();
	cout << "Output right end matrix:" << endl;
	for (int i = 0; i < getSize(); i++)
		cout << sums[i] << " ";
	cout << endl << endl;

	//回代過程
	solution[getSize() - 1] = sums[getSize() - 1] / d;
	for (int i = getSize() - 2; i >= 0; i--){
		double t = 0.0;
		for (int j = i + 1; j <= getSize() - 1; j++)
			t += element(i, j)*solution[j];//實際上不是單位矩陣
		solution[i] = sums[i] - t;
	}
	js[getSize() - 1] = getSize() - 1;//最後一行最後一列主元素就是本列
	for (int k = getSize() - 1; k >= 0; k--)
		if (js[k] != k) swap(solution[k], solution[js[k]]);
	delete[] js;
	return true;
}

主函式檔案

#include<iostream>
#include"LinearEqu.h"
using namespace std;
int main(){
	double a[] = {//方程係數矩陣
		0.2368, 0.2471, 0.2568, 1.2671,
		0.1968, 0.2071, 1.2168, 0.2271,
		0.1581, 1.1675, 0.1768, 0.1871,
		1.1161, 0.1254, 0.1397, 0.1490
	};
	double b[] = { 1.8471, 1.7471, 1.6471, 1.5471 };//方程右端項
	LinearEqu equ(4);//定義一個四元方程組物件
	equ.setLinearEqu(a, b);//設定方程組
	equ.printLinearEqu();//輸出方程組
	if (equ.solve())
		equ.printSolution();
	else
		cout << "Fail" << endl;
	return 0;
}

五. 結果

六,分析

其實該方法並不是我們平常手算矩陣解方程組的思路,這個是按照高斯消去法的邏輯將方程組矩陣一步步的轉化,但是最後並沒有轉化為單位矩陣,而是轉化為了邏輯上的階梯矩陣,然後進一步求出解,圖中紅色即為最終化成的矩陣