编程练习:矩阵类

自己尝试以模板的形式写了一个基础矩阵类,提供了矩阵运算的基本方法,包括加减乘除、转置、求行列式、求逆,后续还会进行陆续的补充,下面添上源码,可能存在一些不足之处,希望能得到大家的建议。

//头文件Matrix.h
/*
*@copyright yyh 2017
*/
#pragma once
#include "stdafx.h"
#define CHUDENG 0 //初等变换
#define BANSUI 1//伴随阵
#define REC 0//递归求行列式  速度太慢
#define TRIA 1//上三角求行列式
template<typename T=double>
class Matrix//:private myMat
{
private:
    typedef T value_type;
    T** data;//存放数据
    int cols;//矩阵列
    int rows;//矩阵行
public:
    Matrix();
    Matrix(const int &rows, const int &cols);//构造大小为rows*cols的矩阵
    Matrix(T *p, int rows, int cols);//用二维数组来构造矩阵
    Matrix(const Matrix &m1, const Matrix &m2);//合并两个矩阵
    Matrix(const Matrix &m);//深拷贝构造函数
    void showMatrix();//输出显示整个矩阵
    void zeros();//初始化为0矩阵
    double cofactor(int i, int j);//求i,j处的代数余子式
    bool unit();//初始化为单位阵
    void exchangeRow(const int &i1, const int &i2);//交换矩阵两行
    T* operator[](const int &i);//通过下标访问数矩阵元素
    Matrix& operator=(const Matrix & m);//重载赋值运算符实现深拷贝
    Matrix Trans();//矩阵转置
    double det(int method=TRIA);//求矩阵行列式
    Matrix operator*(Matrix & m);//矩阵相乘
    Matrix operator+(Matrix & m);//矩阵相加
    Matrix operator-(Matrix & m);//矩阵相减
    template<typename T, typename S> friend Matrix operator*(Matrix & m, S num);//矩阵乘以一个数
    template<typename T, typename S> friend Matrix operator*(S num,Matrix & m );//矩阵乘以一个数
    template<typename T, typename S> friend Matrix operator/(Matrix & m, S num);//矩阵除以一个数
    Matrix inverse(int method=CHUDENG);//矩阵求逆
    ~Matrix();
};

cpp文件

#include "stdafx.h"
#include "Matrix.h"
//构造函数
template<typename T>
Matrix::Matrix()
{
    data = NULL;
    rows = 0;
    cols = 0;
}
template<typename T>
Matrix::Matrix(const int &rows, const int &cols)
{
    data = new T* [rows];
    for (int i = 0; i < rows; i++)
        data[i] = new T[cols];
    this->cols = cols;
    this->rows = rows;
}
//用二维数组来构造矩阵
template<typename T>
Matrix::Matrix(T *p, int rows, int cols)
{
    this->rows = rows;
    this->cols = cols;
    data = new T*[rows];
    for (int i = 0; i < rows; i++)
    {
        data[i] = new T[cols];
        memcpy(data[i], p + i*cols, sizeof(T)*cols);
    }

}
template<typename T>
Matrix::Matrix(const Matrix &m){
    this->cols = m.cols;
    this->rows = m.rows;
    data = new T*[rows];
    for (int i = 0; i < rows; i++)
    {
        data[i] = new T[cols];
        memcpy(data[i], m.data[i], sizeof(T)*cols);
    }
}
//矩阵合并构造函数
template<typename T>
Matrix::Matrix(const Matrix &m1, const Matrix &m2)
{
    if (m1.rows != m2.rows) exit(0);
    cols = m1.cols + m2.cols;
    rows = m1.rows;
    data = new T*[rows];
    for (int i = 0; i < rows; i++)
    {
        data[i] = new T[cols];
        memcpy(data[i], m1.data[i], sizeof(T)*m1.cols);
        memcpy(data[i]+ m1.cols, m2.data[i], sizeof(T)*m2.cols);
    }
}
//输出显示整个矩阵
template<typename T>
void Matrix::showMatrix(){
    //控制台下有效
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
            cout << data[i][j] << " ";
        cout << endl;
    }
}
//重载赋值运算符
template<typename T>
Matrix& Matrix::operator=(const Matrix & m)
{
    for (int i = 0; i < rows; i++)
        delete[] data[i];
    delete[]data;
    this->cols = m.cols;
    this->rows = m.rows;
    data = new T*[rows];
    for (int i = 0; i < rows; i++)
    {
        data[i] = new T[cols];
        memcpy(data[i], m.data[i], sizeof(T)*cols);
    }
    return *this;
}

template<typename T>
T* Matrix::operator[](const int &i){
    return data[i];
}
//0矩阵
template<typename T>
void Matrix::zeros(){
    for (int i = 0; i < rows;i++)
    for (int j = 0; j < cols; j++)
        data[i][j] = 0;
}
//单位阵
template<typename T>
bool Matrix::unit(){
    if (rows != cols) return false;
    this->zeros();
    for (int i = 0; i < rows; i++)
        data[i][i] = 1;
    return true;
}
//交换矩阵的两行
template<typename T>
void  Matrix::exchangeRow(const int &i1, const int &i2)
{
    T *tmp = new T[cols];
    memcpy(tmp, data[i1], sizeof(T)*cols);
    memcpy(data[i1], data[i2], sizeof(T)*cols);
    memcpy(data[i2], tmp, sizeof(T)*cols);
    delete[]tmp;
}
//矩阵转置
template<typename T>
Matrix Matrix::Trans(){
    Matrix m(cols, rows);
    for (int i = 0; i < rows; i++)
    for (int j = 0; j < cols; j++)
        m[i][j] = this->data[j][i];
    return m;
}
//求矩阵行列式
template<typename T>
double Matrix::det(int method){
    if (rows != cols) exit(0);
    double result=0;
    int q = 1;
    if (cols == 1){
        result = data[0][0];
        return result;
    }
    if (method == REC)
    {
        for (int i = 0; i < cols; i++)
        {
            Matrix M(cols - 1, cols - 1);//代数余子式
            for (int u = 0; u < M.rows; u++)
            for (int v = 0; v < M.cols; v++)
            {
                if (v < i)
                    M[u][v] = data[u + 1][v];
                else
                    M[u][v] = data[u + 1][v + 1];
            }
            if (i % 2 == 0) q = 1; else q = -1;
            if (data[0][i] == 0) continue;
            else
                result += data[0][i] * q*M.det();//递归求行列式
        }
        return result;
    }
    if (method == TRIA)
    {
        Matrix M(*this);
        for (int i = 0; i < rows; i++)
        {
            if (M.data[i][i] == 0)
            {
                for (int j = i + 1; j < rows; j++)
                {
                    if (M.data[j][i] != 0)
                    {
                        M.exchangeRow(i, j);
                        q = -1;
                        goto outer;
                    }
                }
                result = 0;
                return result;
            }
        outer:
            for (int u = i+1; u < rows; u++)
            {
                if (M.data[u][i] == 0) continue;
                for (int v = i + 1; v < cols; v++)
                {
                    M.data[u][v] = M.data[u][v] - M.data[u][i] / M.data[i][i] * M.data[i][v];
                }
            }
        }
        result = 1;
        for (int i = 0; i < rows; i++)
        {
            result *= M.data[i][i];
        }
        return result;
    }
}
//矩阵相乘
template<typename T>
Matrix Matrix::operator*(Matrix & m){
    if (cols != m.rows) exit(0);
    Matrix result(rows,m.cols);
    for (int i = 0; i < result.rows; i++)
    for (int j = 0; j < result.cols; j++)
    {
        result[i][j] = 0;
        for (int k = 0; k < cols; k++)
            result[i][j] += data[i][k] * m[k][j];
    }
    return result;
}
//矩阵乘以一个数
template<typename T,typename S>
Matrix operator*(Matrix & m, S num)
{
    Matrix result(m.rows, m.cols);
    for (int i = 0; i < m.rows;i++)
    for (int j = 0; j < m.cols; j++)
    {
        result.data[i][j] = num*m.data[i][j];
    }
    return result;
}
//矩阵乘以一个数
template<typename T, typename S>
Matrix operator*(S num,Matrix & m)
{
    return m*num;
}
//矩阵除以一个数
template<typename T, typename S>
Matrix operator/(Matrix & m, S num)
{
    Matrix result(m.rows, m.cols);
    for (int i = 0; i < m.rows; i++)
    for (int j = 0; j < m.cols; j++)
    {
        result.data[i][j] = m.data[i][j]/num;
    }
    return result;
}
//矩阵相加
template<typename T>
Matrix Matrix::operator+(Matrix & m){
    if (cols != m.cols || rows != m.rows) exit(0);
    Matrix result(rows,cols);
    for (int i = 0; i < result.rows; i++)
    for (int j = 0; j < result.cols; j++)
    {
        result[i][j] = data[i][j] + m[i][j];
    }
    return result;
}
//矩阵相减
template<typename T>
Matrix Matrix::operator-(Matrix & m){
    if (cols != m.cols || rows != m.rows) exit(0);
    Matrix result(rows, cols);
    for (int i = 0; i < result.rows; i++)
    for (int j = 0; j < result.cols; j++)
    {
        result[i][j]= data[i][j] - m[i][j];
    }
    return result;
}
//矩阵求逆
template<typename T>
Matrix Matrix::inverse(int method)
{
    if (rows != cols) exit(0);
    Matrix result(rows,cols);
    //初等行变换求逆矩阵
    if (method == CHUDENG)
    {
        Matrix m(rows, cols);
        m.unit();
        Matrix expand_Matrix(*this, m);//定义扩展矩阵,左边为原矩阵,右边为单位阵
        //调整矩阵
        for (int i = 0; i < rows; i++)
        {
            if (expand_Matrix[i][i] == 0)//如果某行对角线元素等于0,搜索其它行不为0的元素的值
            {
                for (int j = i + 1; j < rows; j++)
                {
                    if (expand_Matrix[j][i] != 0)//交换这两行
                    {
                        expand_Matrix.exchangeRow(i, j);
                        goto outer;
                    }
                }
                exit(0);//矩阵行列式为0,程序退出
            }
        outer:
            for (int j = i+1; j < expand_Matrix.cols; j++)
            {
                expand_Matrix[i][j] /= expand_Matrix[i][i];
            }
            expand_Matrix[i][i] = 1;
            //把其它行在该列的值变为0
            for (int t = 0; t < rows; t++)
            {
                if (t == i) continue;
                for (int j = i + 1; j < expand_Matrix.cols; j++)
                {
                    expand_Matrix[t][j] = expand_Matrix[t][j] - expand_Matrix[i][j] * expand_Matrix[t][i];
                }
                expand_Matrix[t][i] = 0;
            }
        }
        for (int i = 0; i < rows;i++)
        for (int j = 0; j < cols; j++)
        {
            result[i][j] = expand_Matrix[i][j + cols];
        }
        return result;
    }
    //伴随矩阵法求逆
    if (method == BANSUI)
    {
        double D = this->det();
        if (D == 0) exit(0);
        for (int i = 0; i < rows;i++)
        for (int j = 0; j < cols; j++)
        {
            result[i][j] = this->cofactor(j, i) / D;
        }
        return result;
    }
}
//求i,j处的代数余子式
template<typename T>
double Matrix::cofactor(int i, int j)
{
    if (rows != cols) exit(0);
    int p = 0;
    if (p % 2 == 0) p = 1; else p = -1;
    Matrix M(rows - 1, cols - 1);//代数余子式
    for (int u = 0; u < M.rows; u++)
    for (int v = 0; v < M.cols; v++)
    {
        if (u < i&&v< j)
            M[u][v] = data[u][v];
        else if (u=j)
            M[u][v] = data[u][v + 1];
        else if (u>=i&&v1][v];
        else
            M[u][v] = data[u + 1][v+1];
    }
    return M.det()*p;
}
//析构函数
template<typename T>
Matrix::~Matrix()
{
    for (int i = 0; i < rows; i++)
        delete[] data[i];
    delete[]data;
}

你可能感兴趣的:(编程练习)