高斯消去法解線性方程組C++實現
阿新 • • 發佈:2019-01-01
一.問題分析:高斯消去法解線性方程組主要面對的問題是矩陣的運算,所以可以定義一個矩陣類Matrix類作為基類,然後由矩陣類Matrix類派生出一個線性方程組類LinearEqu類。
二.矩陣功能分析:(1)Matrix類處理n*n的方陣,方陣用一個一維陣列存放,矩陣類Matrix的資料成員包括陣列的首地址和矩陣長度n,函式成員有設定矩陣的值setMatrix()和顯示矩陣printMatrix()。(2)LinearEqu類除了由矩陣Matrix繼承過來的存放矩陣A的成員之外,還包括存放解向量X
注: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;
}
五. 結果
六,分析
其實該方法並不是我們平常手算矩陣解方程組的思路,這個是按照高斯消去法的邏輯將方程組矩陣一步步的轉化,但是最後並沒有轉化為單位矩陣,而是轉化為了邏輯上的階梯矩陣,然後進一步求出解,圖中紅色即為最終化成的矩陣