https://blog.csdn.net/guxch/article/details/110795047
https://www.zhihu.com/question/403570202/answer/1351024448
逆矩阵求解算法参考https://blog.csdn.net/qithon/article/details/80100029?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165873888016781667819434%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=165873888016781667819434&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-80100029-null-null.142
https://blog.csdn.net/m0_46201544/article/details/125012646?ops_request_misc=&request_id=&biz_id=102&utm_term=%20C++%20
矩阵幂运算,快速幂算法参考https://blog.csdn.net/qq_34401994/article/details/104646211
高斯滤波算法参考https://blog.csdn.net/dcrmg/article/details/52304446?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162400765316780366538782%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=162400765316780366538782&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-1-52304446.pc_search_result_before_js&utm_term=c%2B%2B
完整代码// // Created by Xmx on 2022/7/26. // #include作业要求:#include #include #include using namespace std; template class Matrix { public: // 无参构造函数 Matrix() {} // 有参构造函数 Matrix(int rows, int cols, T init_value) { set_rows(rows); set_cols(cols); new_mat(); for (int i = 0; i < get_rows(); ++i) for (int j = 0; j < get_cols(); ++j) mat_[i][j] = init_value; } // 析构函数 ~Matrix() { cout << "~Matrix" << endl; delete_mat(); } // done: // 有参构造函数, 使用初始化列表 Matrix(initializer_list > listList) { rows_ = (listList.begin())->size(); cols_ = listList.size(); new_mat(); // 分配内存 auto pr = listList.begin(); auto pc = pr->begin(); for (int i = 0; i < get_rows(); i++, pr++) { pc = pr->begin(); for (int j = 0; j < get_cols(); j++, pc++) mat_[i][j] = *pc; } } // 重载拷贝构造函数, 实现深拷贝 Matrix (const Matrix &matrix) { this->rows_ = matrix.get_rows(); this->cols_ = matrix.get_cols(); new_mat(); // 为拷贝接受对象开辟内存 //拷贝数值 for (int i = 0; i < matrix.get_rows(); ++i) for (int j = 0; j < matrix.get_cols(); ++j) mat_[i][j] = matrix.mat_[i][j]; } //! 重载= 必须通过成员函数实现 Matrix &operator=(const Matrix &matrix) { // 若其在堆区, 先释放mat_指针,再深拷贝即可 if (mat_ != NULL) { delete mat_; mat_ = NULL; } // 深拷贝 this->rows_ = matrix.get_rows(); this->cols_ = matrix.get_cols(); new_mat(); for (int i = 0; i < matrix.get_rows(); ++i) for (int j = 0; j < matrix.get_cols(); ++j) mat_[i][j] = matrix.mat_[i][j]; return *this; } bool operator==(const Matrix &other) { if (this->rows_ == other.rows_ && this->cols_ == other.cols_) { if (this->mat_ != NULL && other.mat_ != NULL) { for (int i = 0; i < this->rows_; i++) for (int j = 0; j < this->cols_; j++) if (this->mat_[i][j] != other.mat_[i][j]) return false; return true; } else return false; } else return false; } bool operator!=(const Matrix &other) { if (this->rows_ == other.rows_ && this->cols_ == other.cols_) { if (this->mat_ != NULL && other.mat_ != NULL) { for (int i = 0; i < this->rows_; i++) for (int j = 0; j < this->cols_; j++) if (mat_[i][j] != other.mat_[i][j]) return true; return true; } else return true; } else return true; } // 申请矩阵空间 void new_mat() { this->mat_ = new T *[get_rows()]; for (int i = 0; i < get_rows(); i++) { this->mat_[i] = new T[get_cols()]; } } // 释放矩阵空间 void delete_mat() { if (mat_ != NULL) { for (int i = 0; i < get_rows(); i++) delete[] this->mat_[i]; delete[] mat_; mat_ = NULL; } } // * ------------------------- 访问器与修改器 ---------------------------- * void set_rows(int rows) { this->rows_ = rows; } void set_cols(int cols) { this->cols_ = cols; } int get_rows() const { return this->rows_; } int get_cols() const { return this->cols_; } / // read_contents += temp; // } // cout << read_contents << endl; if (input.is_open()) { int rows, cols; input >> rows >> cols; set_rows(rows); set_cols(cols); new_mat(); for (int i = 0; i < get_rows(); i++) for (int j = 0; j < get_cols(); j++) input >> mat_[i][j]; cout << "read the txt successfully" << endl; cout << "rows: " << rows << " cols: " << cols << endl; input.close(); cout << "The Matrix has been read successfully: " << endl; cout << *this << endl; } else cout << "File Opening Failed" << endl; } void write_matrix(string filename) { ofstream output(filename); if (output.is_open()) { output << *this << endl; output.close(); cout << "Matrix has been written" << endl; } else cout << "File Opening Failed" << endl; } // void show_mat() // { // cout << endl; // for (int i = 0; i < get_rows(); i++) // { // for (int j = 0; j < get_cols(); j++) // { // cout << this->mat_[i][j] << " "; // } // cout << endl; // } // cout << endl; // } // * ------------------------ 矩阵的基本运算函数 -------------------------- * void swap_element(T &element1, T &element2) { T temp = element1; element1 = element2; element2 = temp; } // 交换两行 void swap_rows(int row1, int row2) { for (int i = 0; i < get_cols(); i++) swap_element(mat_[row1][i], mat_[row2][i]); } // 交换两列 void swap_cols(int col1, int col2) { for (int i = 0; i < get_rows(); i++) swap_element(mat_[i][col1], mat_[i][col2]); } // * ------------------------- 运算符重载的友元声明 ------------------------ * template friend istream &operator>>(istream &in, Matrix &A); //! >> template friend ostream &operator<<(ostream &out, Matrix &A); //! << template friend Matrix operator+(const Matrix &A, const U &k); //! A + k template friend Matrix operator+(const U &k, const Matrix &A); //! k + A template friend Matrix operator-(const Matrix &A, const U &k); //! A - k template friend Matrix operator-(const U &k, const Matrix &A); //! k - A template friend Matrix operator*(const U &k, const Matrix &A); //! k * A template friend Matrix operator*(const Matrix &A, const U &k); //! A * k template friend Matrix operator/(const U &k, const Matrix &A); //! k / A template friend Matrix operator/(const Matrix &A, const U &k); //! A / k template friend Matrix operator+(const Matrix &A, const Matrix &B); //! A + B template friend Matrix operator-(const Matrix &A, const Matrix &B); //! A - B template friend Matrix operator*(const Matrix &A, const Matrix &B); //! A * B template friend Matrix operator/(const Matrix &A, const Matrix &B); //! A / B template friend Matrix operator^(const Matrix &A, const U &B); //! A^k / // 零矩阵 static Matrix zeros(int rows, int cols) { return Matrix (rows, cols, 0); } // 单位矩阵 static Matrix units(int size) { Matrix result = Matrix ::zeros(size, size); // 先生成一个size大小的 "方零矩阵" for (int i = 0; i < result.get_cols(); i++) // 修改对角线元素 result.mat_[i][i] = 1; return result; } //! done: 求逆矩阵(高斯消元实现) template static Matrix inverse(const Matrix &A) { double eps = 1e-6; // 返回double类型,防止精度丢失 Matrix temp = Matrix ::augmented_E(A); for (int i = 0; i < temp.get_rows(); i++) { if (fabs(temp.mat_[i][i]) < eps) { int j; for (j = i + 1; j < temp.get_rows(); j++) if (fabs(temp.mat_[i][j]) > eps) break; } // 初等变换实现消元 for (int i = 0; i < temp.get_rows(); i++) { double t = temp.mat_[i][i]; // 将temp.mat_[i][i] = 1; for (int j = i; j < temp.get_cols(); j++) temp.mat_[i][j] /= t; for (int j = i + 1; j < temp.get_rows(); j++) { double tt = -1 * (temp.mat_[j][i] / temp.mat_[i][i]); for (int k = i; k < temp.get_cols(); k++) temp.mat_[j][k] += tt * temp.mat_[i][k]; } } } for (int i = temp.get_rows() - 1; i >= 0; i--) { for (int j = i - 1; j >= 0; j--) { double tt = -1 * (temp.mat_[j][i] / temp.mat_[i][i]); for (int k = i; k < temp.get_cols(); k++) temp.mat_[j][k] += tt * temp.mat_[i][k]; } } // 将temp左半部分传给result Matrix result(A.get_rows(), A.get_cols(), 0); for (int i = 0; i < result.get_rows(); i++) for (int j = result.get_rows(); j < 2 * result.get_rows(); j++) result.mat_[i][j - result.get_rows()] = temp.mat_[i][j]; // cout< augmented_E(const Matrix &A) { int rows = A.get_rows(); int cols = A.get_rows() + A.get_cols(); Matrix result = Matrix (rows, cols, 0); for (int i = 0; i < result.get_rows(); i++) { for (int j = 0; j < result.get_cols(); j++) { if (j < A.get_cols()) { result.mat_[i][j] = A.mat_[i][j]; } else { if (j == A.get_cols() + i) result.mat_[i][j] = 1; else result.mat_[i][j] = 0; } } } return result; } //! done: 增广矩阵A' , 返回A的增广矩阵 static Matrix augmented(const Matrix &A, const T *input, int len) { int rows = A.get_rows(); int cols = A.get_rows() + 1; for (int i = 0; i < len; i++) cout << input[i] << " "; // input数组长度为A的行数满足条件,可以生成增广矩阵 if (len == rows) { Matrix result = Matrix (rows, cols, 0); for (int i = 0; i < result.get_rows(); i++) { for (int j = 0; j < result.get_cols(); j++) { if (j < A.get_cols()) result.mat_[i][j] = A.mat_[i][j]; else result.mat_[i][j] = input[i]; } } return result; } else return Matrix ::zeros(1, 1); } //! done: 高斯消元(初等变换法)求解线性方程 static string Gauss_eliminate(const Matrix &A) { Matrix temp = A; // 用于计算的矩阵 double ratio = 0, eps = 1e-6; // 默认最小主元素 int n = temp.get_rows(); // 方程个数 double result[n]; // 存储结果的数组 string result_string = ""; // 消元 for (int k = 0; k < (n); k++) { for (int i = (k + 1); i < n; i++) { if (abs(temp.mat_[k][k]) < eps) return "No solution!"; double ratio = temp.mat_[i][k] / temp.mat_[k][k]; for (int j = (k + 1); j < (n + 1); j++) temp.mat_[i][j] -= ratio * temp.mat_[k][j]; temp.mat_[i][k] = 0; } } result[n - 1] = temp.mat_[n - 1][n] / temp.mat_[n - 1][n - 1]; // 回代 for (int i = (n - 2); i >= 0; i--) { double sum = 0; for (int j = (i + 1); j < n; j++) { sum += temp.mat_[i][j] * result[j]; result[i] = (temp.mat_[i][n] - sum) / temp.mat_[i][i]; } } // 生成结果字符串 for (int i = 0; i < n; i++) result_string += "nresult[" + to_string(i) + "]=" + to_string(result[i]) + "n"; return result_string; } //! done: 高斯核矩阵 static Matrix Gauss_kernel(int size, double sigma) { Matrix result = Matrix ::zeros(size, size); const double PI = 4.0 * atan(1.0); // 圆周率赋值 int center = size / 2; double sum = 0; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { result.mat_[i][j] = (1 / (2 * PI * sigma * sigma)) * exp(-((i - center) * (i - center) + (j - center) * (j - center)) / (2 * sigma * sigma)); sum += result.mat_[i][j]; } } return result; } //! done: H 为高斯滤波核矩阵, A 需要高斯滤波的矩阵, 返回滤波后的矩阵 static Matrix Gauss_filter(const Matrix &A, const Matrix &H) { Matrix result = Matrix::zeros(A.get_rows(), A.get_cols()); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < result.get_cols(); j++) result.mat_[i][j] = A.mat_[i][j] * H.mat_[i][j]; return result; } private: int rows_; int cols_; T **mat_; }; / //! done: 重载>> template istream &operator>>(istream &in, Matrix &A) { cout << "Input the rows and columns for the matrix" << endl; in >> A.rows_ >> A.cols_; A.new_mat(); for (int i = 0; i < A.get_rows(); i++) for (int j = 0; j < A.get_cols(); j++) in >> A.mat_[i][j]; return in; } //! done: 重载<< template ostream &operator<<(ostream &out, Matrix &A) { for (int i = 0; i < A.get_rows(); i++) { out << " ["; for (int j = 0; j < A.get_cols(); j++) out << " " << A.mat_[i][j]; out << " ]" << endl; } out << endl; return out; } //! done A + k template Matrix operator+(const Matrix &A, const U &k) { if (A.get_cols() == A.get_rows()) // A 为方针,可以运算 { Matrix result = Matrix(A); for (int i = 0; i < result.get_cols(); i++) // A + kE result.mat_[i][i] += k; return result; } else // 无法运算,返回1×1单位矩阵 return Matrix::zeros(1, 1); } //! done k + A template Matrix operator+(const U &k, const Matrix &A) { if (A.get_cols() == A.get_rows()) // A 为方针,可以运算 { Matrix result = Matrix(A); for (int i = 0; i < result.get_cols(); i++) // kE + A result.mat_[i][i] += k; return result; } else // 无法运算,返回1×1单位矩阵 return Matrix::zeros(1); } //! done: A - k template Matrix operator-(const Matrix &A, const U &k) { if (A.get_cols() == A.get_rows()) // A 为方针,可以运算 { Matrix result = Matrix(A); for (int i = 0; i < result.get_cols(); i++) // A - kE result.mat_[i][i] -= k; return result; } else // 无法运算,返回1×1单位矩阵 return Matrix::zeros(1); } //! done k - A template Matrix operator-(const U &k, const Matrix &A) { if (A.get_cols() == A.get_rows()) // A 为方针,可以运算 { Matrix result = Matrix(A); for (int i = 0; i < result.get_cols(); i++) // kE - A for (int j = 0; j < result.get_cols(); j++) { if (i == j) result.mat_[i][j] = k - result.mat_[i][j]; else result.mat_[i][j] = -result.mat_[i][j]; } return result; } else // 无法运算,返回1×1单位矩阵 return Matrix::zeros(1); } //! done: k * A template Matrix operator*(const U &k, const Matrix &A) { Matrix result = Matrix(A); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < result.get_cols(); j++) result.mat_[i][j] = result.mat_[i][j] * k; return result; } //! done: A * k template Matrix operator*(const Matrix &A, const U &k) { Matrix result = Matrix(A); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < result.get_cols(); j++) result.mat_[i][j] = result.mat_[i][j] * k; return result; } //! done: k / A template Matrix operator/(const U &k, const Matrix &A) { // k / A = kE * A^-1 // A 为方针,可以运算 if (A.get_rows() == A.get_cols()) { Matrix result = Matrix(A); Matrix kE = Matrix::units(A.get_rows()); kE = kE * k; // 生成kE return kE * Matrix::inverse(A); } else // 无法运算,返回零矩阵 return Matrix::zeros(1, 1); } //! done: A / k template Matrix operator/(const Matrix &A, const U &k) { Matrix result = Matrix(A); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < result.get_cols(); j++) result.mat_[i][j] = result.mat_[i][j] / k; return result; } //! done: A + B template Matrix operator+(const Matrix &A, const Matrix &B) { // A 与 B 维度相同 if ((A.get_cols() == B.get_cols()) && (A.get_rows() == B.get_rows())) { Matrix result = Matrix(A); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < B.get_cols(); j++) result.mat_[i][j] += B.mat_[i][j]; return result; } else // 无法运算,返回零矩阵 return Matrix::zeros(1, 1); } //! done: A - B template Matrix operator-(const Matrix &A, const Matrix &B) { // A 与 B 维度相同 if ((A.get_cols() == B.get_cols()) && (A.get_rows() == B.get_rows())) { Matrix result = Matrix(A); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < B.get_cols(); j++) result.mat_[i][j] -= B.mat_[i][j]; return result; } else // 无法运算,返回零矩阵 return Matrix::zeros(1, 1); } //! done: A * B template Matrix operator*(const Matrix &A, const Matrix &B) { // 先判断能否运算 if (A.get_cols() == B.get_rows()) { Matrix result = Matrix(A.get_rows(), B.get_cols(), 0); for (int i = 0; i < result.get_rows(); i++) for (int j = 0; j < result.get_cols(); j++) for (int k = 0; k < result.get_cols(); k++) // 所在行所在列元素相乘 result.mat_[i][j] += A.mat_[i][k] * B.mat_[k][j]; return result; } else // 无法运算,返回零矩阵 return Matrix::zeros(1, 1); } //! done: A / B template Matrix operator/(const Matrix &A, const Matrix &B) { // A / B == A * B^-1 // 先判断能否运算 if (A.get_cols() == B.get_rows()) return A * (Matrix::inverse(B)); else return Matrix::zeros(1, 1); } //! done: A^k template Matrix operator^(const Matrix &A, int k) { Matrix result = Matrix::units(A.get_cols()); Matrix temp = A; // 快速幂进行运算 while (k) { if (k % 2) result = result * temp; k /= 2; temp = temp * temp; } return result; } int main() { // Matrix matrix1(3, 3, 3); // Matrix matrix1_4(3, 4, 4); // Matrix matrix2(4, 4, 4); // // Matrix matrix3 = { {5,5,-1,7,54},{4,-9,20,12,-6},{9,-18,-3,1,21},{ 61,-8,-10,3,13 },{ 29,-28,-1,4,14 } }; // // Matrix matrix4 = Matrix (matrix1); // Matrix matrix5 = matrix1_4 * (0.3); // Matrix matrix6 = Matrix ::units(3); // matrix1.show_mat(); // matrix2.show_mat(); // // matrix3.show_mat(); // // matrix4.show_mat(); // matrix5.show_mat(); // matrix6.show_mat(); // cout< matrix = Matrix ::augmented_E(matrix1_4); // matrix.swap_rows(0,1); // cout << matrix; // Matrix matrix10; // cin >> matrix10; // Matrix temp = Matrix ::inverse(matrix10); // Matrix temp1 = Matrix ::inverse(matrix10); // cout << temp; // temp = temp ^ 2; // cout< m1(3, 3, 3); Matrix m2(3, 3, 4); cout << m1 << m2 << endl; cout << (m1 == m2); // double input[] = {6,18,7}; // cout<<"len = "<< sizeof(input)/sizeof(input[0])< Equations; // cin >> Equations; // Equations = Matrix ::augmented(Equations,input,sizeof(input)/sizeof(input[0])); // cout<< Equations; // cout<< Matrix ::Gauss_eliminate(Equations); //! 测试高斯滤波 Matrix temp(5, 5, 100); cout << temp << endl; temp = Matrix ::Gauss_filter(temp, Matrix ::Gauss_kernel(5, 5)); cout << temp; //! 测试文件和流 // Matrix matrix_IO; // matrix_IO.load_matrix("input.txt"); // matrix_IO.write_matrix("output.txt"); // 测试初始化列表 initializer_list > initializerL_mat = {{1, 2, 3}, {2, 2, 2}, {3, 3, 3}}; Matrix matrix_initializer(initializerL_mat); cout << matrix_initializer; }
- 实现一个矩阵类,包含以下功能:
基本成员
a) rows_行,cols_列,double** mat,矩阵元素
b) get_rows()返回行数;get_cols()返回列数
- 矩阵类的构造函数
a) 默认构造函数,生成一个1,1列的矩阵
Matrix mat;
b) 生成行列分别为rows, cols的矩阵
Matrix mat(rows, cols);
c) 生成行列分别为rows, cols,初始值为init_value的矩阵
Matrix mat(rows, cols, init_value);
d) 利用初始化列表生成矩阵
Matrix mat = {{1,2,3,4}, {5,6,7,8}};
-
析构函数
-
拷贝构造函数与赋值运算符函数(实现深拷贝)
-
实现基本运算符重载函数,其中 A 表示矩阵,k表示标量(一个实数)。如表1所示。
-
静态函数生成基本矩阵
a) 零矩阵 Matrix::zeros(rows, cols);
b) 单位矩阵 Matrix::eye(size);
c) 均匀分布随机矩阵[1] Matrix::randu(rows, cols);
d) 高斯分布随机矩阵[2] Matrix::randn(rows, cols);
矩阵类基本运算符
| 操作符 | 说明 |
|---|---|
| A + k | 矩阵对应元素加上标量 |
| k + A | 标量加上矩阵对应元素 |
| A - k | 矩阵对应元素减去标量 |
| A ∗ k | 矩阵对应元素乘以标量 |
| k ∗ A | 标量乘以矩阵对应元素 |
| A + B | 矩阵对应元素加法 |
| A - B | 矩阵对应元素减法 |
| A * B | 矩阵乘法 |
| A % B | 矩阵对应元素乘法 |
| A / B | 矩阵对应元素乘法 |
| A ^ k | 矩阵 A 的 k 次幂 (可以采用矩阵快速幂实现) |
- 应用于方程组的矩阵函数
a) 增广矩阵 Matrix Ab = AugmentMatrix(A, B);
对于矩阵A,B的构成的增广矩阵Ab为
其中A,B矩阵的行数数应保证相同。
b) 逆矩阵 Matrix IA = Inverse(A);
逆矩阵可以通过对增广矩阵IA做高斯消元法实现,其中,I 是矩阵A的同型单位矩阵。
c) 实现高斯消元法求解线性方程组 Matrix x = GaussianElimination(A, b);
- 高斯滤波
a) 生成高斯核 Matrix H = GaussianKernel(k, sigma); 其中k表示高斯核尺寸, sigma表示方差。
b) 实现高斯滤波 Matrix B = GaussianFilter(A, H)
- 实现成员函数实现将矩阵读写函数。比如
Matrix mat;
mat.Load(filename);
mat.Write(filename);



