矩阵
这是小白在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/