最近实现一个算法要用到求逆等矩阵运算,在网上搜到一个别人写的矩阵类,试了一下效果不错,贴在这里,做个保存。

matrix.h文件:

 #ifndef __MATRIX_H__
#define __MATRIX_H__ #pragma once #include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string> using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::istream;
using std::ostream; // 任意类型矩阵类
template <typename Object>
class MATRIX
{
public:
explicit MATRIX() : array( ) {} MATRIX( int rows, int cols):array( rows )
{
for( int i = ; i < rows; ++i )
{
array[i].resize( cols );
}
} MATRIX( const MATRIX<Object>& m ){ *this = m;} void resize( int rows, int cols ); // 改变当前矩阵大小
bool push_back( const vector<Object>& v ); // 在矩阵末尾添加一行数据
void swap_row( int row1, int row2 ); // 将换两行的数据 int rows() const{ return array.size(); }
int cols() const { return rows() ? (array[].size()) : ; }
bool empty() const { return rows() == ; } // 是否为空
bool square() const { return (!(empty()) && rows() == cols()); } // 是否为方阵 const vector<Object>& operator[](int row) const { return array[row]; } //[]操作符重载
vector<Object>& operator[](int row){ return array[row]; } protected:
vector< vector<Object> > array;
}; // 改变当前矩阵大小
template <typename Object>
void MATRIX<Object>::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 = ; i < rows; ++i )
{
array[i].resize( cols );
}
}
else if ( rows != rs && cols == cs )
{
array.resize( rows );
for ( int i = rs; i < rows; ++i )
{
array[i].resize( cols );
}
}
else
{
array.resize( rows );
for ( int i = ; i < rows; ++i )
{
array[i].resize( cols );
}
}
} // 在矩阵末尾添加一行
template <typename Object>
bool MATRIX<Object>::push_back( const vector<Object>& v )
{
if ( rows() == || cols() == (int)v.size() )
{
array.push_back( v );
}
else
{
return false;
} return true;
} // 将换两行
template <typename Object>
void MATRIX<Object>::swap_row( int row1, int row2 )
{
if ( row1 != row2 && row1 >= &&
row1 < rows() && row2 >= && row2 < rows() )
{
vector<Object>& v1 = array[row1];
vector<Object>& v2 = array[row2];
vector<Object> tmp = v1;
v1 = v2;
v2 = tmp;
}
} // 矩阵转置
template <typename Object>
const MATRIX<Object> trans( const MATRIX<Object>& m )
{
MATRIX<Object> ret;
if ( m.empty() ) return ret; int row = m.cols();
int col = m.rows();
ret.resize( row, col ); for ( int i = ; i < row; ++i )
{
for ( int j = ; j < col; ++j )
{
ret[i][j] = m[j][i];
}
} return ret;
} //////////////////////////////////////////////////////////
// double类型矩阵类,用于科学计算
// 继承自MATRIX类
// 实现常用操作符重载,并实现计算矩阵的行列式、逆以及LU分解
class Matrix:public MATRIX<double>
{
public:
Matrix():MATRIX<double>(){}
Matrix( int c, int r ):MATRIX<double>(c,r){}
Matrix( const Matrix& m){ *this = m; } const Matrix& operator+=( const Matrix& m );
const Matrix& operator-=( const Matrix& m );
const Matrix& operator*=( const Matrix& m );
const Matrix& operator/=( const Matrix& m );
}; bool operator==( const Matrix& lhs, const Matrix& rhs ); // 重载操作符==
bool operator!=( const Matrix& lhs, const Matrix& rhs ); // 重载操作符!=
const Matrix operator+( const Matrix& lhs, const Matrix& rhs ); // 重载操作符+
const Matrix operator-( const Matrix& lhs, const Matrix& rhs ); // 重载操作符-
const Matrix operator*( const Matrix& lhs, const Matrix& rhs ); // 重载操作符*
const Matrix operator/( const Matrix& lhs, const Matrix& rhs ); // 重载操作符/
const double det( const Matrix& m ); // 计算行列式
const double det( const Matrix& m, int start, int end ); // 计算子矩阵行列式
const Matrix abs( const Matrix& m ); // 计算所有元素的绝对值
const double max( const Matrix& m ); // 所有元素的最大值
const double max( const Matrix& m, int& row, int& col); // 所有元素中的最大值及其下标
const double min( const Matrix& m ); // 所有元素的最小值
const double min( const Matrix& m, int& row, int& col); // 所有元素的最小值及其下标
const Matrix trans( const Matrix& m ); // 返回转置矩阵
const Matrix submatrix(const Matrix& m,int rb,int re,int cb,int ce); // 返回子矩阵
const Matrix inverse( const Matrix& m ); // 计算逆矩阵
const Matrix LU( const Matrix& m ); // 计算方阵的LU分解
const Matrix readMatrix( istream& in = std::cin ); // 从指定输入流读入矩阵
const Matrix readMatrix( string file ); // 从文本文件读入矩阵
const Matrix loadMatrix( string file ); // 从二进制文件读取矩阵
void printMatrix( const Matrix& m, ostream& out = std::cout ); // 从指定输出流打印矩阵
void printMatrix( const Matrix& m, string file); // 将矩阵输出到文本文件
void saveMatrix( const Matrix& m, string file); // 将矩阵保存为二进制文件 #endif

matrix.cpp文件:

 #include "Matrix.h"
#include <iomanip> //用于设置输出格式 using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::cerr;
using std::endl; const Matrix& Matrix::operator+=( const Matrix& m )
{
if ( rows() != m.rows() || rows() != m.cols() )
{
return *this;
} int r = rows();
int c = cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
array[i][j] += m[i][j];
}
} return *this;
} const Matrix& Matrix::operator-=( const Matrix& m )
{
if ( rows() != m.rows() || cols() != m.cols() )
{
return *this;
} int r = rows();
int c = cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
array[i][j] -= m[i][j];
}
} return *this;
} const Matrix& Matrix::operator*=( const Matrix& m )
{
if ( cols() != m.rows() || !m.square() )
{
return *this;
} Matrix ret( rows(), cols() ); int r = rows();
int c = cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
double sum = 0.0;
for ( int k = ; k < c; ++k )
{
sum += array[i][k] * m[k][j];
}
ret[i][j] = sum;
}
} *this = ret;
return *this;
} const Matrix& Matrix::operator/=( const Matrix& m )
{
Matrix tmp = inverse( m );
return operator*=( tmp );
} bool operator==( const Matrix& lhs, const Matrix& rhs )
{
if ( lhs.rows() != rhs.rows() || lhs.cols() != rhs.cols() )
{
return false;
} for ( int i = ; i < lhs.rows(); ++i )
{
for ( int j = ; j < lhs.cols(); ++j )
{
if ( rhs[i][j] != rhs[i][j] )
{
return false;
}
}
} return true;
} bool operator!=( const Matrix& lhs, const Matrix& rhs )
{
return !( lhs == rhs );
} const Matrix operator+( const Matrix& lhs, const Matrix& rhs )
{
Matrix m;
if ( lhs.rows() != rhs.rows() || lhs.cols() != rhs.cols() )
{
return m;
} m = lhs;
m += rhs; return m;
} const Matrix operator-( const Matrix& lhs, const Matrix& rhs )
{
Matrix m;
if ( lhs.rows() != rhs.rows() || lhs.cols() != rhs.cols() )
{
return m;
} m = lhs;
m -= rhs; return m;
} const Matrix operator*( const Matrix& lhs, const Matrix& rhs )
{
Matrix m;
if ( lhs.cols() != rhs.rows() )
{
return m;
} m.resize( lhs.rows(), rhs.cols() ); int r = m.rows();
int c = m.cols();
int K = lhs.cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
double sum = 0.0;
for ( int k = ; k < K; ++k )
{
sum += lhs[i][k] * rhs[k][j];
}
m[i][j] = sum;
}
} return m;
} const Matrix operator/( const Matrix& lhs, const Matrix& rhs )
{
Matrix tmp = inverse( rhs );
Matrix m; if ( tmp.empty() )
{
return m;
} return m = lhs * tmp;
} inline static double LxAbs( double d )
{
return (d>=)?(d):(-d);
} inline
static bool isSignRev( const vector<double>& v )
{
int p = ;
int sum = ;
int n = (int)v.size(); for ( int i = ; i < n; ++i )
{
p = (int)v[i];
if ( p >= )
{
sum += p + i;
}
} if ( sum % == ) // 如果是偶数,说明不变号
{
return false;
}
return true;
} // 计算方阵行列式
const double det( const Matrix& m )
{
double ret = 0.0; if ( m.empty() || !m.square() ) return ret; Matrix N = LU( m ); if ( N.empty() ) return ret; ret = 1.0;
for ( int i = ; i < N.cols(); ++ i )
{
ret *= N[i][i];
} if ( isSignRev( N[N.rows()-] ))
{
return -ret;
} return ret;
} // 计算矩阵指定子方阵的行列式
const double det( const Matrix& m, int start, int end )
{
return det( submatrix(m, start, end, start, end) );
} // 计算矩阵转置
const Matrix trans( const Matrix& m )
{
Matrix ret;
if ( m.empty() ) return ret; int r = m.cols();
int c = m.rows(); ret.resize(r, c);
for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
ret[i][j] = m[j][i];
}
} return ret;
} // 计算逆矩阵
const Matrix inverse( const Matrix& m )
{
Matrix ret; if ( m.empty() || !m.square() )
{
return ret;
} int n = m.rows(); ret.resize( n, n );
Matrix A(m); for ( int i = ; i < n; ++i ) ret[i][i] = 1.0; for ( int j = ; j < n; ++j ) //每一列
{
int p = j;
double maxV = LxAbs(A[j][j]);
for ( int i = j+; i < n; ++i ) // 找到第j列中元素绝对值最大行
{
if ( maxV < LxAbs(A[i][j]) )
{
p = i;
maxV = LxAbs(A[i][j]);
}
} if ( maxV < 1e- )
{
ret.resize(,);
return ret;
} if ( j!= p )
{
A.swap_row( j, p );
ret.swap_row( j, p );
} double d = A[j][j];
for ( int i = j; i < n; ++i ) A[j][i] /= d;
for ( int i = ; i < n; ++i ) ret[j][i] /= d; for ( int i = ; i < n; ++i )
{
if ( i != j )
{
double q = A[i][j];
for ( int k = j; k < n; ++k )
{
A [i][k] -= q * A[j][k];
}
for ( int k = ; k < n; ++k )
{
ret[i][k] -= q * ret[j][k];
}
}
}
} return ret;
} // 计算绝对值
const Matrix abs( const Matrix& m )
{
Matrix ret; if( m.empty() )
{
return ret;
} int r = m.rows();
int c = m.cols();
ret.resize( r, c ); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
double t = m[i][j];
if ( t < ) ret[i][j] = -t;
else ret[i][j] = t;
}
} return ret;
} // 返回矩阵所有元素的最大值
const double max( const Matrix& m )
{
if ( m.empty() ) return .; double ret = m[][];
int r = m.rows();
int c = m.cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
if ( m[i][j] > ret ) ret = m[i][j];
}
}
return ret;
} // 计算矩阵最大值,并返回该元素的引用
const double max( const Matrix& m, int& row, int& col )
{
if ( m.empty() ) return .; double ret = m[][];
row = ;
col = ; int r = m.rows();
int c = m.cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
if ( m[i][j] > ret )
{
ret = m[i][j];
row = i;
col = j;
}
}
}
return ret;
} // 计算矩阵所有元素最小值
const double min( const Matrix& m )
{
if ( m.empty() ) return .; double ret = m[][];
int r = m.rows();
int c = m.cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
if ( m[i][j] > ret ) ret = m[i][j];
}
} return ret;
} // 计算矩阵最小值,并返回该元素的引用
const double min( const Matrix& m, int& row, int& col)
{
if ( m.empty() ) return .; double ret = m[][];
row = ;
col = ;
int r = m.rows();
int c = m.cols(); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
if ( m[i][j] > ret )
{
ret = m[i][j];
row = i;
col = j;
}
}
} return ret;
} // 取矩阵中指定位置的子矩阵
const Matrix submatrix(const Matrix& m,int rb,int re,int cb,int ce)
{
Matrix ret;
if ( m.empty() ) return ret; if ( rb < || re >= m.rows() || rb > re ) return ret;
if ( cb < || ce >= m.cols() || cb > ce ) return ret; ret.resize( re-rb+, ce-cb+ ); for ( int i = rb; i <= re; ++i )
{
for ( int j = cb; j <= ce; ++j )
{
ret[i-rb][j-cb] = m[i][j];
}
} return ret;
} inline static
int max_idx( const Matrix& m, int k, int n )
{
int p = k;
for ( int i = k+; i < n; ++i )
{
if ( LxAbs(m[p][k]) < LxAbs(m[i][k]) )
{
p = i;
}
}
return p;
} // 计算方阵 M 的 LU 分解
// 其中L为对角线元素全为1的下三角阵,U为对角元素依赖M的上三角阵
// 使得 M = LU
// 返回矩阵下三角部分存储L(对角元素除外),上三角部分存储U(包括对角线元素)
const Matrix LU( const Matrix& m )
{
Matrix ret; if ( m.empty() || !m.square() ) return ret; int n = m.rows();
ret.resize( n+, n ); for ( int i = ; i < n; ++i )
{
ret[n][i] = -1.0;
} for ( int i = ; i < n; ++i )
{
for ( int j = ; j < n; ++j )
{
ret[i][j] = m[i][j];
}
} for ( int k = ; k < n-; ++k )
{
int p = max_idx( ret, k, n );
if ( p != k ) // 进行行交换
{
ret.swap_row( k, p );
ret[n][k] = (double)p; // 记录将换信息
} if ( ret[k][k] == 0.0 )
{
cout << "ERROR: " << endl;
ret.resize(,);
return ret;
} for ( int i = k+; i < n; ++i )
{
ret[i][k] /= ret[k][k];
for ( int j = k+; j < n; ++j )
{
ret[i][j] -= ret[i][k] * ret[k][j];
}
}
} return ret;
} //---------------------------------------------------
// 读取和打印
//---------------------------------------------------
// 从输入流读取矩阵
const Matrix readMatrix( istream& in )
{
Matrix M;
string str;
double b;
vector<double> v; while( getline( in, str ) )
{
for ( string::size_type i = ; i < str.size(); ++i )
{
if ( str[i] == ',' || str[i] == ';')
{
str[i] = ' ';
}
else if ( str[i] != '.' && (str[i] < '' || str[i] > '')
&& str[i] != ' ' && str[i] != '\t' && str[i] != '-')
{
M.resize(,);
return M;
}
} istringstream sstream(str);
v.resize(); while ( sstream >> b )
{
v.push_back(b);
}
if ( v.size() == )
{
continue;
}
if ( !M.push_back( v ) )
{
M.resize( , );
return M;
}
} return M;
} // 从文本文件读入矩阵
const Matrix readMatrix( string file )
{
ifstream fin( file.c_str() );
Matrix M; if ( !fin )
{
cerr << "Error: open file " << file << " failed." << endl;
return M;
} M = readMatrix( fin );
fin.close(); return M;
} // 将矩阵输出到指定输出流
void printMatrix( const Matrix& m, ostream& out )
{
if ( m.empty() )
{
return;
} int r = m.rows();
int c = m.cols(); int n = ; // 数据小数点前最大位数
double maxV = max(abs(m));
while( maxV >= 1.0 )
{
maxV /= ;
++n;
}
if ( n == ) n = ; // 如果最大数绝对值小于1,这小数点前位数为1,为数字0
int pre = ; // 小数点后数据位数
int wid = n + pre + ; // 控制字符宽度=n+pre+符号位+小数点位 out<<std::showpoint;
out<<std::setiosflags(std::ios::fixed);
out<<std::setprecision( pre );
for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
out<<std::setw(wid) << m[i][j];
}
out << endl;
} out<<std::setprecision();
out<<std::noshowpoint;
} // 将矩阵打印到指定文件
void printMatrix( const Matrix& m, string file )
{
ofstream fout( file.c_str() );
if ( !fout ) return; printMatrix( m, fout );
fout.close();
} // 将矩阵数据存为二进制文件
void saveMatrix( const Matrix& m, string file )
{
if ( m.empty() ) return; ofstream fout(file.c_str(), std::ios_base::out|std::ios::binary );
if ( !fout ) return; int r = m.rows();
int c = m.cols();
char Flag[] = "MATRIX_DATA";
fout.write( (char*)&Flag, sizeof(Flag) );
fout.write( (char*)&r, sizeof(r) );
fout.write( (char*)&c, sizeof(c) ); for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
double t = m[i][j];
fout.write( (char*)&t, sizeof(t) );
}
} fout.close();
} // 从二进制文件load矩阵
const Matrix loadMatrix( string file )
{
Matrix m; ifstream fin( file.c_str(), std::ios_base::in|std::ios::binary );
if ( !fin ) return m; char Flag[];
fin.read((char*)&Flag, sizeof(Flag)); string str( Flag );
if ( str != "MATRIX_DATA" )
{
return m;
} int r, c;
fin.read( (char*)&r, sizeof(r) );
fin.read( (char*)&c, sizeof(c) ); if ( r <= || c <= ) return m; m.resize( r, c );
double t; for ( int i = ; i < r; ++i )
{
for ( int j = ; j < c; ++j )
{
fin.read( (char*)&t, sizeof(t) );
m[i][j] = t;
}
} return m;
}

C++实现矩阵求逆的更多相关文章

  1. 矩阵求逆算法及程序实现(C++)

    在做课题时,遇到了求多项式问题,利用了求逆方法.矩阵求逆一般使用简单的算法,还有快速算法 如全选主元高斯-约旦消元法,但本文程序主要写了简单的矩阵求逆算法定义法之伴随矩阵求逆公式如下,其中A可逆: , ...

  2. matrix矩阵求逆 与解方程模板 留做备用 (有bug,待补充)

    // // main.cpp // 矩阵求逆 // // Created by 唐 锐 on 13-6-20. // Copyright (c) 2013年 唐 锐. All rights reser ...

  3. 矩阵求逆的几种方法总结(C++)

    矩阵求逆运算有多种算法: 伴随矩阵的思想,分别算出其伴随矩阵和行列式,再算出逆矩阵: LU分解法(若选主元即为LUP分解法: Ax = b ==> PAx = Pb ==>LUx = Pb ...

  4. RLS自适应滤波器中用矩阵求逆引理来避免求逆运算

    在RLS自适应滤波器的实现过程中,难免不涉及矩阵的求逆运算.而求逆操作双是非常耗时的,一个很自然的想法就是尽可能的避免直接对矩阵进行求逆运算.那么,在RLS自适应滤波器的实现中,有没有一种方法能避免直 ...

  5. 矩阵求逆·学习笔记 $\times$ [$LuoguP4783$]矩阵求逆

    哦?今天在\(luogu\)上fa♂现了矩阵求逆的板子--于是就切了切. 那么我们考虑一个矩阵\(A\),它的逆矩阵记作\(A^{-1}\),其中对于矩阵这个群来讲,会有\(A \cdot A^{-1 ...

  6. 【题解】Matrix BZOJ 4128 矩阵求逆 离散对数 大步小步算法

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4128 大水题一道 使用大步小步算法,把数字的运算换成矩阵的运算就好了 矩阵求逆?这么基础的线 ...

  7. BZOJ 4128 Matrix BSGS+矩阵求逆

    题意:链接 方法: BSGS+矩阵求逆 解析: 这题就是把Ax=B(mod C)的A和B换成了矩阵. 然而别的地方并没有修改. 所以就涉及到矩阵的逆元这个问题. 矩阵的逆元怎么求呢? 先在原矩阵后接一 ...

  8. BZOJ 1444 [JSOI2009]有趣的游戏 (Trie图/AC自动机+矩阵求逆)

    题目大意:给你$N$个长度相等且互不相同的模式串,现在有一个字符串生成器会不断生成字符,其中每个字符出现的概率是$p_{i}/q_{i}$,当生成器生成的字符串包含了某个模式串,则拥有该模式串的玩家胜 ...

  9. LG4783 【模板】矩阵求逆

    P4783 [模板]矩阵求逆 题目描述 求一个$N\times N$的矩阵的逆矩阵.答案对$10^9+7$取模. 输入输出格式 输入格式: 第一行有一个整数$N$,代表矩阵的大小: 从第$2$行到第$ ...

  10. LUOGU P4783 【模板】矩阵求逆(高斯消元)

    传送门 解题思路 用高斯消元对矩阵求逆,设\(A*B=C\),\(C\)为单位矩阵,则\(B\)为\(A\)的逆矩阵.做法是把\(B\)先设成单位矩阵,然后对\(A\)做高斯消元的过程,对\(B\)进 ...

随机推荐

  1. 小于等于N的全部整数与N关于gcd(i,N)的那些事

    相关问题1: 求小于等于N的与N互质的数的和.即∑ i (gcd(i,N)=1, N>=i>0) 依据N的规模能够有非常多种方法.这里我介绍一个比較经典的方法 先说下这个结论:假设 gcd ...

  2. Android4.2.2下Stagefright下OMX编解码器组件的控制流

    本文均属自己阅读源代码的点滴总结.转账请注明出处谢谢. 欢迎和大家交流. qq:1037701636 email:gzzaigcn2012@gmail.com Android源代码版本号Version ...

  3. sass10 demo1

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. bzoj1433: [ZJOI2009]假期的宿舍(最大二分图匹配)

    1433: [ZJOI2009]假期的宿舍 题目:传送门 题解: 这题有点水 跑个二分图匹配就完事了(注意在校生不是一定都互相认识) 代码: #include<cstdio> #inclu ...

  5. 8.最佳的MongoDB客户端管理工具

    转自:https://blog.csdn.net/chszs/article/details/51348248

  6. MySQL优化-存储引擎

    MySQL优化-存储引擎 标签(空格分隔): mysql 存储引擎 查看存储引擎 show engines Myisam: 表锁 全文索引 Innodb: 行锁 事物 外键 Memory: 内存存储引 ...

  7. BZOJ 3503 高斯消元

    思路: 高斯消元就好啦 注意每个格子最多只能和4个相邻 所以是 n*m*n*m*5 的 并不会TLE //By SiriusRen #include <cstdio> #include & ...

  8. 那些不兼容 IE11的网站(持续更新)

    此博文用于收集不兼容 IE11 的网站,持续更新,请网站开发者自己认领: 兼容性引起的功能缺陷: v.qq.com (提示未安装 Flash 播放器,这问题我反馈几百年了,还没修复) tv.sohu. ...

  9. java 8 , merge()

    import java.util.HashMap; import java.util.Map; public class j8merge { public static void main(Strin ...

  10. datable

    $("#table_d").append("<table id='dmglTable' class='table table-striped table-hover ...