C++矩阵类的实现

矩阵类对于学习C++的类有很大的帮助,如拷贝构造函数,算术符重载等。以下为设计矩阵类。

class MyMatrix
{
public:
    int  m_nRows; // 矩阵的行数
    int  m_nColumns; // 矩阵的列数
    double* m_lpBuf; // 动态分配用来存放数组的空间
public:
    MyMatrix();
    MyMatrix(MyMatrix& A);
     ~MyMatrix();
}

由于矩阵的行和列都是不固定的,因而,需要将其设为动态分配内存的方式,分配函数如下:

MyMatrix::MyMatrix(int m, int n)//declare an mxn MyMatrix
{
    m_nRows = m;
    m_nColumns = n;
    //需要防止乘法溢出,此处忽略之
    this->m_lpBuf = new double[m*n];
    memset(m_lpBuf,0,m*n*sizeof(double));
}

而析构函数则为:

~MyMatrix(){   
        m_nRows = 0;    
        m_nColumns =0;  
        if(m_lpBuf != NULL)     
            delete[] this->m_lpBuf;
    };

一般的,对于有动态分配内存的类,均需要重写(深)拷贝构造函数,如下函数为深拷贝函数和赋值函数:

MyMatrix::MyMatrix(const MyMatrix& A) //copy ructor
{ 
    this->m_nRows = A.m_nRows;
    this->m_nColumns = A.m_nColumns;
    if(m_nRows * m_nColumns != 0)
    {
        this->m_lpBuf = new double[m_nRows*m_nColumns];

        for(int i = 0;i < (m_nRows*m_nColumns);++i)
            this->m_lpBuf[i] = A.m_lpBuf[i];
    }
    else
        m_lpBuf = NULL;
}  
MyMatrix& MyMatrix::operator = ( const MyMatrix& A) //overloading =
{
    if(this==&A) 
        return *this;
    this->resize(A.m_nRows,A.m_nColumns);

    for(int i=0;i<(m_nColumns*m_nRows);i++)
        m_lpBuf[i] = A.m_lpBuf[i];  
    return *this;
}

对于经常使用Matlab的人,则会喜欢如下的表达方式:a(1,2),对于C++类,同样的可有:

double& MyMatrix::operator ()(int i, int j)
{
    // Unsafe
    return *(m_lpBuf + (i-1)*m_nColumns+(j-1)); 
}

对于重载操作符,可以这么写:

MyMatrix& MyMatrix::operator += ( MyMatrix& A) 
{
    if(!A.m_lpBuf) return *this;
    if ( (this->m_nRows != A.m_nRows) || (this->m_nColumns != A.m_nColumns))
    {
        throw logic_error ("Size mismatch in MyMatrix addition");
    }
    for(int i=0;ithis->m_lpBuf[i]+=A.m_lpBuf[i];

    return *this;
}
MyMatrix operator + (MyMatrix& A, MyMatrix& B) 
{
    MyMatrix tmp = A;
    tmp+=B;
    return tmp;
}

其它的如乘法操作可以依此来写。
对于将矩阵内的数据保存为txt文件和读取txt文件,可以如下编写:

bool MyMatrix::SaveToTxt(const char *filename)
{
    ofstream file(filename,ios_base::out);
    if(!file)
        return false;
    for(int i=1;i<=m_nColumns;++i)
    {
        for(int j=1;j<=m_nRows;++j)
            file<20)<7)<1)*m_nColumns + (j-1));
        file<<"\n"<return true;
}
bool MyMatrix::LoadFromTxt(const char *filename)
{
    FILE *fp = NULL;
    if(fopen_s(&fp,filename,"r")!=0)
        return false;
    int i = 0;
    while(!feof(fp))
    {
        fscanf_s(fp,"%lf",(m_lpBuf+i));
        if(++i>m_nRows*m_nColumns)
            break;
    }
    fclose(fp);
    return true;
}

以下程序对矩阵求逆,其方法即为算术中的计算方法

MyMatrix inv(MyMatrix& A) 
{
    int rows = A.m_nRows;
    MyMatrix C(rows,rows);

    if(A.m_nRows != A.m_nColumns)
        return C; 

    // 构造一个与A行相同的单位阵B = |A : E|
    MyMatrix B(rows, rows*2, 0);
    for(int i = 1;i<=rows;++i)
        for(int j=1;j<=rows;++j)
            B(i,j) = A(i,j);
    for(int i = 1;i<=rows;++i)
        B(i,i+rows) = 1;

    double tempa = 0;
    // 对矩阵A进行B.row次消元运算,每次保证第K列只有对角线上非零 
    for(int k=1; k<=B.m_nRows; k++)
    { 
        //------------------ 选主元 -------------------------------- 
        double max = fabs(B(k,k)); // 主元初始默认为右下方矩阵首个元素 
        int ind = k; // 主元行号默认为右下方矩阵首行 
        // 结果第ind行为列主元行 
        for(int n=k+1; n<=B.m_nRows; ++n)
        { 
            if(fabs(B(n,k)) > max)
            {
                // 遇到绝对值更大的元素 
                max = fabs(B(n,k)); // 更新主元值 
                ind = n; // 更新主元行号
            }
        }
        //------------------- 移动主元行 ------------------------- 
        if(ind != k)
        { // 主元行不是右下方矩阵首行 
            for(int m=k; m<=rows*2; ++m)
            { // 将主元行与右下方矩阵首行互换 
                tempa = B(k,m); 
                B(k,m) = B(ind, m);
                B(ind,m) = tempa;
            }           
        } 

        //--------------------- 消元 -------------------------------- 
        // 第k次消元操作,以第k行作为主元行,将其上下各行的第k列元素化为零 
        // 同时以同样的参数对B施以同样的操作,此时可以将B看作A矩阵的一部分 
        tempa = 1.0/B(k,k);
        for(int i=k; i<=rows*2; ++i)
        {
            B(k,i) *= tempa;
        }

        for(int i=1; i<=rows; i++)
        { 
            if(i != k)
            { 
                tempa = -B(i,k);
                for(int j=k; j<=B.m_nColumns; ++j) 
                    B(i,j) += tempa*B(k,j);
            }//end if 
        }//loop i 

    }//loop k 

    for(int i = 1;i<=rows;++i)
        for(int j = 1;j<=rows;++j)
            C(i,j) = B(i,j+rows);

    return C;
}//inv()

你可能感兴趣的:(矩阵类)