矩阵类的书写(初学小白)

矩阵

这是小白在csdn的第一篇文章,有点紧张。初学所以写了一个基本的矩阵类,主要目的在于实现逆矩阵的运算和求矩阵的秩,多余的代码可以自行取用。希望得到各位大神的指点。

矩阵基类

这里主要是一个分数类的矩阵,关于分数的头文件可以查阅csdn的其他网站,将其包含在路径下即可:
c++分数类
这一块主要实现矩阵的一些基本运算符重载和一些基本的运算,主要的求秩的算法通过初等变换的方式求得。这里定义一个经过初等变化得到的阶梯矩阵,方便于之后求解线性方程组。
代码块逻辑:
matrix 矩阵类
matri,matricg分别保存矩阵和它经过变换之后的阶梯矩阵
operator + - * << >> 重载运算符(都是对于原始矩阵的操作)
rowcheng,linecheng,rowjia,linejia,swaprow,swapline,是一些初等变化函数
getcg打印阶梯矩阵
rankchange用于初始化阶梯矩阵并求矩阵的秩

class matrix {
public:
    int row;//保存行
    int line;//保存列
    bool nullrank;//若rank未判断,则为真,若已经判断,则为假
    int rank;//保存矩阵的秩
    vector<vector<fraction>> matri;//容器矩阵
    vector<vector<fraction>> matricg;//保存该矩阵经过初等变换之后得到的矩阵
    matrix()
    {
        row = line = 0;
        nullrank = true;
        rank = 0;
    }
    matrix(int r, int l) {
        this->row = r;
        this->line = l;
        rank = 0;
        nullrank = true;
        matri.assign(r, vector<fraction>(l,0));
        matricg.assign(r, vector<fraction>(l, 0));//均初始化为0
        matri.shrink_to_fit();
        matricg.shrink_to_fit();//释放空间
    };
    matrix operator+(matrix a)//矩阵相加 
    {
        if (a.row != row || a.line != line) {
            throw"不能相加!";
        }
        matrix temp(row, line);
        for(int i=0;i<row;i++)
            for (int j = 0; j < line; j++) {
                temp.matri[i][j] = matri[i][j] + a.matri[i][j];
            }
        return temp;
    }
    matrix operator-(matrix a)//矩阵相减
    {
        if (a.row != row || a.line != line) {
            throw"不能相减!";
        }
        matrix temp(row, line);
        for (int i = 0; i < row; i++)
            for (int j = 0; j < line; j++) {
                temp.matri[i][j] = matri[i][j] - a.matri[i][j];
            }
        return temp;
    }
    matrix operator*(matrix a)//矩阵相乘
    {
        if (a.row != line) {
            throw"不能相乘";
        }
        matrix temp(row, a.line);
        for (int i = 0; i < row; i++)
            for (int j = 0; j < a.line; j++) {
                for(int z=0;z<a.row;z++)
                temp.matri[i][j] += matri[i][z]*a.matri[z][j];
            }
        return temp;
    }
    friend istream& operator>>(istream& in, matrix& a)//重载输入函数 
    {
        for (int i = 0; i < a.row; i++)
            for (int j = 0; j < a.line; j++)
                in >> a.matri[i][j];
        a.matri.shrink_to_fit();
        return in;
    };
    friend ostream& operator<<(ostream& out, matrix& a)//重载输出函数 
    {
        for (int i = 0; i < a.row; i++) {
            for (int j = 0; j < a.line; j++) {
                out <<setiosflags(ios::left)<<setw(4)<< a.matri[i][j]<<" " ;
            }
            cout << endl;
        }
        return out;
    }
    void getcg() {
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < line; j++) {
                cout<<setiosflags(ios::left) << setw(4)<<matricg[i][j]<<" ";
            }
            cout << endl;
        }
    }
    void swaprow(int i, int j)//i,j行交换 
    {
       matri[i].swap(matri[j]);
    }
    void swapline(int i, int j)//i,j列交换 
    {
        fraction rtemp;
        for (int z = 0; z < this->row; z++)
        {
            rtemp = matri[z][i];
            matri[z][i] = matri[z][j];
            matri[z][j] = rtemp;
        }
    }
    void rowcheng(fraction a, int i) //第i行乘以a倍
    {
        for (int j = 0; j < this->line; j++) {
            matri[i][j] *= a;
        }
    }
    void linecheng(fraction a, int i)//第i列乘以a倍
    {
        cout << a<<endl;
        for (int j = 0; j < this->row; j++) {
            matri[j][i] *= a;
        }
    }
    void rowjia(int i, int j, fraction t) //第i行加上j行的t倍
    {
        for (int z = 0; z < this->line; z++) {
            this->matri[i][z] += t * matri[j][z];
        }
    }
    void linejia(int i, int& j, fraction t)//第i列加上j列的t倍
    {
        for (int z = 0; z < this->line; z++) {
            this->matri[z][i] += t * matri[z][j];
        }
    }
    int findoneline(int j)//找到第j列的第一个非零元素,返回位置
    {
        int rtemp = 0;
        while (matri[rtemp][j] == 0) {
            rtemp++;
        }
        return rtemp;
    }
    int findonerow(int j)//返回第j行第一个非零元素位置 
    {
        int ltemp = 0;
        while (matri[j][ltemp] == 0) { ltemp++; }
        return ltemp;
    }
    void rankchange()//求矩阵的秩阶梯矩阵
    {
        if (nullrank == false) { return; }//已经初始化则返回
        int rank=line;//初始化秩的值
        matricg = matri;//初始化matricg为matri再进行操作
        for (int rowtemp = 0; rowtemp < rank; rowtemp++)
        {
            if (matricg[rowtemp][rowtemp]!=0)//只要对角线元素不为零,那么就将其他行的该列全部改为0
            {
                for (int col = 0; col < row; col++)
                {
                    if (col != rowtemp)
                    {
                        fraction mult = matricg[col][rowtemp]/matricg[rowtemp][rowtemp];
                        for (int i = 0; i < rank; i++)
                            matricg[col][i] -= mult * matricg[rowtemp][i];
                    }
                }
            }
            else//对角线上元素为0
            {
                bool reduce = true;//定义一个减标志,如果在该列没有寻找到不为0的元素,则秩减一
                for (int i = rowtemp + 1; i < row; i++)//寻找不为零的元素行并交换行
                {
                    if (matricg[i][rowtemp]!=0)
                    {
                        matricg[rowtemp].swap(matricg[i]);
                        reduce = false;
                        break;
                    }
                }
                if (reduce)
                {
                    rank--;
                    fraction c;
                    for (int i = 0; i < row; i++) {
                        c=matricg[i][rowtemp];
                        matricg[i][rowtemp]=matricg[i][rank];
                        matricg[i][rank] = c;//交换列
                    }
                }
                rowtemp--;
            }
        }
        nullrank = false;
        matricg.shrink_to_fit();
        return;
    }
    matrix rowconnection(matrix a) {//用于两个矩阵的拼接
        if (a.row != row) { throw"无法拼接!"; }
        vector<vector<fraction>> temp(this->matri);
        for (int i = 0; i < row; i++) {
            temp[i].insert(temp[i].end(), a.matri[i].begin(), a.matri[i].end());
        }
        temp.shrink_to_fit();
        matrix t(row, line + a.line);
        t.matri = temp;
        return t;
    }
};

单位矩阵

这里做了一个继承(不知道这样合不合适,还请各位大神指教)

class identitymatrix :public matrix {
public:identitymatrix(int n) {
        row = line = rank=n;
        nullrank = false;
        matri.assign(n, vector<fraction>(n, 0));
        for (int i = 0; i < n; i++) { matri[i][i] = 1; }
        matricg = matri;
    }
};

方阵

这里是我主要的想要实现的地方,这里做了一个方阵类,其中inverseinit函数将同时初始化矩阵的秩和他的逆矩阵,即通过同样的初等变化得到逆矩阵。
这里重载了上面的函数rankchange,否则将会带来过高的运行代价(想不到什么合适的方法,求指教)。

class squarematrix : public matrix {
public:
    vector<vector<fraction>> inversematri;//增加逆矩阵成员
    bool inversenull, inverseexist;//增加逆矩阵初始化判断和存在判断
    squarematrix(int n)
    {
        row = line = n;
        nullrank = inversenull =inverseexist= true;
        rank = 0;
        matri.assign(n, vector<fraction>(n, 0));
        matricg.assign(n, vector<fraction>(n, 0));//这里不做逆矩阵初始化
    }
    void rankchange() //重载防止函数冲突,减少代价;
    {
        cout << "此操作代价过高,是否进行逆矩阵和阶梯矩阵的同时初始化?(选否不进行初始化)[Y/n]";
        char a;
        cin >> a;
        if (a == 'Y' || a == 'y') { inverseinit(); }
        else { return; }
    }
    void inverseinit() {//建议用此函数同时初始化逆矩阵和秩阶梯矩阵,否则代价较高,
        if (inversenull == false||inverseexist==false) {return; }
        if (nullrank == false && rank != row ) { 
            throw"不存在逆矩阵";
            return;
        }//已初始化则判断是否存在逆矩阵
        if (nullrank == false&&rank==row) { matricg = matri; }//已经初始化秩阶梯矩阵则重新进行初始化
        int rank = line;//初始化秩的值
        inversematri.assign(row, vector<fraction>(row, 0));
        for (int i = 0; i < row; i++) { 
            inversematri[i][i] = 1;
        }//初始化为单位矩阵
        matricg = matri;//初始化matricg为matri再进行操作
        for (int rowtemp = 0; rowtemp < rank; rowtemp++)
        {
            if (matricg[rowtemp][rowtemp] != 0)//只要对角线元素不为零,那么就将其他行的该列全部改为0
            {
                for (int col = 0; col < row; col++)
                {
                    if (col != rowtemp)
                    {
                        fraction mult = matricg[col][rowtemp] / matricg[rowtemp][rowtemp];
                        for (int i = 0; i < rank; i++) {
                            matricg[col][i] -= mult * matricg[rowtemp][i];
                            inversematri[col][i] -= mult * inversematri[rowtemp][i];
                        }
                    }
                }
            }
            else//对角线上元素为0
            {
                bool reduce = true;//定义一个减标志,如果在该列没有寻找到不为0的元素,则秩减一
                for (int i = rowtemp + 1; i < row; i++)//寻找不为零的元素行并交换行
                {
                    if (matricg[i][rowtemp] != 0)
                    {
                        matricg[rowtemp].swap(matricg[i]);
                        inversematri[rowtemp].swap(inversematri[i]);
                        reduce = false;
                        break;
                    }
                }
                if (reduce)
                {
                    rank--;
                    fraction c;
                    for (int i = 0; i < row; i++) {
                        c = matricg[i][rowtemp];
                        matricg[i][rowtemp] = matricg[i][rank];
                        matricg[i][rank] = c;//交换列
                    }
                }
                rowtemp--;
            }
        }
        nullrank = false;
        matricg.shrink_to_fit();
        if (rank != row) 
        {
            inversematri.clear();
            inverseexist = false;
            inversenull = false;
            return;
        } 
        inversenull = false;
        for (int i = 0; i < row; i++) 
        {
            if(matricg[i][i]!=1)
                for (int j = 0; j < line; j++) { inversematri[i][j] /= matricg[i][i]; }
        }
        return;
    };
    void printinverse() {
        if ( inverseexist == false) { cout << "没有逆矩阵哦"; return; }
        if (inversenull == true) { cout << "矩阵为空,可能未进行初始化"; }
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < line; j++) {
                cout << setw(4) << inversematri[i][j] << " ";
            }
            cout << endl;
        }
    }
};

下面是一个方阵的实例
在这里插入图片描述
文章参考:
https://blog.csdn.net/liqiangzju/article/details/54645419
https://www.geeksforgeeks.org/program-for-rank-of-matrix/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值