C++ Matrix类(考试太忙了,新增了正交化的QR分解,求逆运算等)

越来越觉得当初考虑这个类的设计时是不对了,这么写下去扩展性太差了,只有自己看的懂了,考试完重新写一下,添加一些注释
/************************************************************************
	> File Name: Matrix.h
	> Author:keson 
	> Mail:keson@bupt.edu.cn 
	> Created Time: 2014年12月22日 星期一 20时08分49秒
 ************************************************************************/

#ifndef _MATRIX_H
#define _MATRIX_H

#include<iostream>
#include<fstream>
#include<vector>
#include<cmath>
#include<sstream>
#include<algorithm>
#include<iomanip>
using namespace std;

class Matrix
{
public:

    Matrix(int i,int j):rowSize(i),colSize(j)
    {
      mat=vector<vector<double>>(i,vector<double>(j));
    }

    //构造函数,读入矩阵,并保存行数和列数
    Matrix(istream &in);
    
    //打印矩阵
    void matPrint();
    
    //获取行数和列数
    int getRowNum() const{return rowSize;}
    int getColNum() const{return colSize;}


    //行列交换
    void changeRow(int ri,int rj);
    void changeCol(int ci,int cj);

    //高斯全主元消元法
    void gaussEliminate();

    //LU 分解
    void LU(vector<vector<double>> &l,vector<vector<double>> &u);

    //求行列式的值
    double gaussDet();

    void inv(vector<vector<double>> &INV);

   
    //获取矩阵
    vector<vector<double>>& getMat()
    {
        return mat;
    }

   
    double getValue(int i,int j)
    {
        return mat[i-1][j-1];
    }


    //获取行元素
    vector<double> getRow(int i);
    
    //获取列元素
    vector<double> getCol(int j);


    //求两向量内积
    double dot(const vector<double> &v1,const vector<double> &v2)
    {
        double ret=0;
        for(int i=0;i<v1.size();i++)
            ret+=v1[i]*v2[i];

        return ret;
    }


    //计算向量长度
    
    double vecLen(const vector<double> &vec)
    {
        double ret;
        for(auto v:vec)
        {
            ret+=v*v;
        }

        return sqrt(ret);
    }
    
    void Schmidt(vector<vector<double>> &q);

    void QR_Schmidt(vector<vector<double>> &Q,vector<vector<double>> &R);


    //矩阵相乘
    Matrix matMulti(const Matrix &mat2);

private:
    vector<vector<double>> mat;
    int rowSize;
    int colSize;
};

//高斯列主元求逆
void Matrix::inv(vector<vector<double>> &INV)
{
    int index=0;
    for(auto &r:INV)
      r[index++]=1;

    int i,j,k,rs,cs;
    double tmp,d;

    for(k=0;k<=rowSize-1;++k)
    {
        d=0.0;
        //选择该列最大元素
        for(i=k;i<=rowSize-1;++i)
        {
            if(fabs(mat[i][k])>d)
            {
                d=mat[i][k];
                rs=i;
            }
        }

        //交换单位矩阵I对应的行和,并按照主元素归一化,注意下标+1对应

        if(k!=rs)
        {
        changeRow(k,rs);
        std::swap(INV[k],INV[rs]);
        }

        tmp=mat[k][k];
        //消元
        for(auto &v:mat[k])
        v=v/tmp;
        for(auto &v:INV[k])
        v=v/tmp;

        for(i=0;i<=rowSize-1;i++)
        {
            if(i!=k)
            {
              tmp=mat[i][k]/mat[k][k];
              for(j=0;j<=colSize-1;++j)
              {
                mat[i][j]=mat[i][j]-tmp*mat[k][j];
                if(fabs(mat[i][j])<=1e-10)
                   mat[i][j]=0;

                INV[i][j]=INV[i][j]-tmp*INV[k][j];
               }
            }
        }
    }
/*
   for(i=0;i<=rowSize-2;i++)
   {
       tmp=mat[i][colSize-1]/mat[rowSize-1][colSize-1];
       for(j=0;j<=colSize-1;j++)
       {
           INV[i][j]=INV[i][j]-tmp*INV[rowSize-1][j];
       }
   }
*/
}

//高斯全主元化为上三角后求行列式的值
double Matrix::gaussDet()
{
    gaussEliminate();
    int ret=1;
    int index=0;
    for(auto v:mat)
    {
        ret*=v[index++];
    }
    return ret;
}

Matrix::Matrix(istream &in)
{
    string line;
    double word;
    vector<double> vec;
    while (getline(in,line))
    {
        istringstream record(line);
        while(record>>word)
          vec.push_back(word);

        mat.push_back(vec);
        colSize=vec.size();
        vec.clear();
    }
    rowSize=mat.size();
}

void Matrix::changeRow(int ri,int rj)
{
    std::swap(mat[ri],mat[rj]);
}

void Matrix::changeCol(int ci,int cj)
{
    for(auto &v:mat)
      std::swap(v[ci],v[cj]);
}

//高斯全主元消元法求上三角
void Matrix::gaussEliminate()
{
    int i,j,k,rs,cs;
    double tmp,d;

    for(k=0;k<=rowSize-2;++k)
    {
        d=0.0;
        for(i=k;i<=rowSize-1;++i)
        {
         for(j=k;j<=colSize-1;++j)
         { 
            if(fabs(mat[i][j])>d)
           {
              d=mat[i][j];
              rs=i;
              cs=j;
           }
         }
        }
       
        if(k!=rs)
        changeRow(k,rs);
        if(k!=cs)
        changeCol(k,cs);
       
        d=mat[k][k];

        for(i=k+1;i<=rowSize-1;++i)
        {
            double tmp=mat[i][k]/mat[k][k];
            for(j=k;j<=colSize-1;++j)
            {
              mat[i][j]=mat[i][j]-tmp*mat[k][j];
              if (fabs(mat[i][j])<=1e-10)
                mat[i][j]=0;
            }
        }
    }
}

/*
 * LU decomposition
 * LU(vector<vector<double>> &l,vector<vector<double>> &u)
 */

 void Matrix::LU(vector<vector<double>> &l,vector<vector<double>> &u)
 {
     int index=0;
     for(auto &r:l)
     {
         r[index++]=1;
     }

     for(auto v:mat)
       u.push_back(v);

     double d=0.0;
     for(int k=0;k<rowSize-1;++k)
     {
         for(int i=k+1;i<=rowSize-1;++i)
         {
           l[i][k]=u[i][k]/u[k][k];
           for(int j=k;j<=colSize-1;++j)
             {
                 u[i][j]=u[i][j]-l[i][k]*u[k][j];
                 if(fabs(u[i][j])<1e-10)
                  u[i][j]=0;
                 
             }

         }
     }
 }


void Matrix::Schmidt(vector<vector<double>> &q)
{

    for(int j=2;j<=colSize;j++)
    {
        double ret;
        double retk;
        for(int k=1;k<j;k++)
        {
           ret=dot(getCol(j),getCol(k));
           retk=dot(getCol(k),getCol(k));
          
          for(auto &r:mat)
            {
                r[j-1]=r[j-1]-ret/retk*r[k-1];
            }
        }
    }

    for(int j=1;j<=colSize;j++)
    {
        double b=vecLen(getCol(j));
        for(auto &r:mat)
        {
            r[j-1]=r[j-1]/b;
        }
    }
    q=mat;
}


void Matrix::QR_Schmidt(vector<vector<double>> &Q,vector<vector<double>> &R)
{
    int index=0;
    for(auto &vec:R)
    {
        vec[index++]=1;
    }

    for(int j=2;j<=colSize;j++)
    {
        double ret;
        double retk;
        for(int k=1;k<j;k++)
        {
           ret=dot(getCol(j),getCol(k));
           retk=dot(getCol(k),getCol(k));
            R[k-1][j-1]=ret/retk;
          for(auto &r:mat)
            {
                r[j-1]=r[j-1]-ret/retk*r[k-1];
            }
        }
    }

    for(int j=1;j<=colSize;j++)
    {
        double b=vecLen(getCol(j));

        for(auto &v:R[j-1])
        {
            v=v*b;
        }
        for(auto &r:mat)
        {
            r[j-1]=r[j-1]/b;
        }
    }
    Q=mat;

}

/**
 * vector<double> getRow(int i)
 * return the i row
 */

vector<double> Matrix::getRow(int i)
{
    return mat[i-1];
}

/**
 * vector<double> getCol(int j)
 */
vector<double> Matrix::getCol(int j)
{
    vector<double> col;
    for(auto c:mat)
      col.push_back(c[j-1]);
    return col;
}

/**
 * Matrix multiplication
 * matrix1=m*n   matrix2=n*k   matrix3=m*k
 */

Matrix Matrix::matMulti(const Matrix &matrix2)
{
    if(getColNum()!=matrix2.getRowNum())
    {
        cout<<"The col of mat1 is not equal the row of the mat2"<<endl;
    }
    int m=getRowNum();
    int n=getColNum();
    int k=matrix2.getColNum();

    Matrix matrix3(m,k);
    for(int i=0;i<m;++i)
        for (int j=0;j<k;++j)
          for(int l=0;l<n;++l)
            matrix3.mat[i][j]+=mat[i][l]*matrix2.mat[l][j];
    return matrix3;
}

/**
 * print the mat;
 */
void Matrix::matPrint()
{
    for(auto c:mat)
    {
        for(auto w:c)
        {
            cout<<setiosflags(ios::fixed);
            cout<<setw(10)<<setprecision(3)<<w;
        }
        cout<<endl;
    }
}

#endif

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值