概述
C++矩阵类的实现
环境:Win10、VS2017
最近老师布置一个简单的C++作业——实现一个矩阵类,并且实现矩阵运算。
主要实现运算为矩阵的加、减、乘、除以及求行列式,伴随矩阵,代数余子式和逆矩阵等。在参考网上的一些前辈的代码后,写出了这些运算的简单实现。
因为矩阵的加、减、乘、除(完成求逆矩阵后)、转置等运算比较简单,所以此处主要讲上述其余运算的实现。
话不多说,开始:
首先定义一个矩阵类,需要实现功能略多,还有各运算函数的声明,大概如下:
class Matrix
{
public:
Matrix(): DataArray(0) {}
Matrix(int rows, int cols) :DataArray(rows)
{
for (int i = 0; i < rows; i++)
DataArray[i].resize(cols);
}
Matrix(const Matrix &m) { (*this) = m; }
friend istream&operator>>(istream &is, Matrix &A); //重载运算符>>用于输入矩阵
friend ostream&operator<<(ostream &os, const Matrix &A); //重载运算符<<用于输出矩阵
//加、减、乘
const Matrix& operator+=(const Matrix &A);
.........
//需要用到一些的函数
void resize(int, int); //改变矩阵大小
bool push_back(const vector<T>& v) { DataArray.push_back(v); } //添加一行
void swap_row(int ,int ); //交换矩阵的两行
int rows() const { return DataArray.size(); }
int cols() const { return rows() ? (DataArray[0].size()) : 0; }
bool empty() const { return rows() == 0; }
bool square() const { return !(empty()) && rows() == cols(); } //判断矩阵是否为方阵
const vector<double> operator[](int row) const { return DataArray[row]; } //这两行用于取矩阵元素
vector<double>& operator[](int row) { return DataArray[row]; }
protected:
vector<vector<double>>DataArray;
};
const double det(const Matrix &A); //求行列式
const double alge_cofactor(const Matrix &A, int row, int col);//求代数余子式
const Matrix adjoint(const Matrix &A); //求伴随矩阵
const Matrix inv(const Matrix &A); //求逆矩阵
矩阵类定义完成,接下来完成resize函数,swap_row比较简单此处不再展出
void Matrix::resize(int rows, int cols)
{
int rs = this->rows();
int cs = this->cols();
if (rows == rs && cols == cs)
{
return;
}
else if (rows == rs && cols != cs) //改列数
{
for (int i = 0;i < rows; i++)
{
DataArray[i].resize(cols);
}
}
else if (rows != rs && cols == cs) //改行数
{
DataArray.resize(rows);
for (int i = rs; i < rows; i++)
{
DataArray[i].resize(cols);
}
}
else //二者都改
{
DataArray.resize(rows);
for (int i = 0; i < rows; i++)
{
DataArray[i].resize(cols);
}
}
}
接下来进入正题,求行列式,代数余子式,伴随矩阵和逆矩阵。步骤如下:
1.求行列式|A|,因为需要计算的行列式阶数并不是很高,所以我选择的求行列式方式为使用公式: ∑ ( − 1 ) t a 1 p 1 a 2 p 2 a 1 p 3 . . . . . . a n p n sum(-1)^ta_{1p_1}a_{2p_2}a_{1p_3}......a_{np_n} ∑(−1)ta1p1a2p2a1p3......anpn,该公式也比较容易实现。然而在完成该函数之前需要先完成 p 1 p_1 p1到 p n p_n pn的全排列,以及排列完成后各逆序数:
1)排列算法函数,不了解可自行搜索,比较简单,大概实现即用一个vector<int> p
存储一种排列然后用vector<<int>> q
存储全排列。
void swap(vector<int>& v, int i, int j)
{
int temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void Permutation(vector<int> &p, vector<vector<int>> &q,int c)
{
if (c == ((unsigned int)p.size() - 1))
{
q.push_back(p);
}
else
{
for (int i = c; i < (unsigned int)p.size(); i++)
{
swap(p, i, c);
Permutation(p, q, c + 1);
swap(p, i, c);
}
}
}
2)求逆序数t:
int Power(vector<int>& v)
{
int count = 0;
for (int i = 0; i < (unsigned int)v.size(); i++)
{
for (int j = i + 1; j < (unsigned int)v.size(); j++)
{
if (v[i] > v[j])
{
count += 1;
}
}
}
return count;
}
3)求行列式,上面两步完成后,求行列式的步骤变得极其简单:
const double det(const Matrix &A)
{
if (!A.square()) //此处可自行修改
{
cout << "fail" << endl;
return 0.0;
}
//完成p1到pn的排列组合
vector<int> rs;
vector<vector<int> > I;
for (int i = 0; i < A.rows(); i++) //输入1-n
{
rs.push_back(i);
}
Permutation(rs, I);
double result = 0.0;
for (int i = 0; i < I.size(); i++)
{
rs= I[i]; //取出一种排列
int temp = pow(-1.0, (double)Power(rs)); //算出该排列的逆序数
int row = 0;
for (int j = 0; j < (unsigned int)rs.size(); j++) //计算一种排列对应的乘积
{
int col = rs[j];
temp *= A[row][col];
row++;
}
result += temp;
}
return result;
}
2.完成求代数余子式的函数,将划去行列元素放入一个新的矩阵,然后求解(其实求出行列式后,剩下三个函数会变得极其简单)。
const double alge_cofactor(const Matrix &A, int row, int col)
{
if (!A.square())
{
cout << "fail" << endl;
return 0.0;
}
vector<int> rs;
vector<vector<int> > I;
vector<double> ret;
Matrix B((A.rows() - 1), (A.cols() - 1));
for (int i = 0; i < A.rows(); i++) //把组成行列式的元素移到ret中
{
if (i == (row-1))
continue;
for (int j = 0; j < A.cols(); j++)
{
if (j == (col-1))
continue;
else
ret.push_back(A[i][j]);
}
}
int count = 0; //剩下的元素组成一个新的行列式
for (int i = 0; i < B.rows(); i++)
{
for (int j = 0; j < B.cols(); j++)
{
B[i][j] = ret[count];
count++;
}
}
double result = det(B)*pow(-1, (double)(row + col));
return result;
}
3.求伴随矩阵,A*:
const Matrix adjoint(const Matrix &A)
{
Matrix B(A.rows(), A.cols());
for (int i = 0; i < A.rows(); i++)
{
for (int j = 0; j < A.cols(); j++)
{
B[i][j] = alge_cofactor(A, (j + 1), (i + 1));
}
}
return B;
}
4.求逆矩阵,使用公式 A − 1 = A ∗ ∣ A ∣ A^{-1}=frac{A^*}{|A|} quad A−1=∣A∣A∗即可:
const Matrix inv(const Matrix &A)
{
if (det(A) == 0||A.rows()!=A.cols())
return A;
else
{
return (adjoint(A) / det(A)); //该处需要重载一下 / 函数声明:const Matrix operator/(const Matrix A, double a);实现矩阵乘一个分数或者说除以一个数
}
}
只需要测试一下矩阵求逆是否正确,即可验证一下其余函数的正确性,测试结果:
虽然可能还存在着很多问题,但是基本上完成任务了。最后感谢那些为我提供参考的前辈们。
最后
以上就是尊敬冥王星为你收集整理的#C++矩阵类的实现的全部内容,希望文章能够帮你解决#C++矩阵类的实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复