为了在原位拆分矩阵(即不复制它),您需要一个可以同时处理原始和拆分部分的表示 - 这将使定义递归算法等变得更加容易:
template <class elt> class MatRef {
elt* m_data;
unsigned m_rows, m_cols;
unsigned m_step;
unsigned index(unsigned row, unsigned col)
{
assert(row < m_rows && col < m_cols);
return m_step * row + col;
}
public: // access
elt& operator() (unsigned row, unsigned col)
{
return m_data[index(row,col)];
}
public: // constructors
MatRef(unsigned rows, unsigned cols, elt* backing) // original matrix
: m_rows(rows)
, m_cols(cols)
, m_step(cols)
, m_data(backing)
{}
MatRef(unsigned start_row, unsigned start_col,
unsigned rows, unsigned cols, MatRef &orig) // sub-matrix
: m_rows(rows)
, m_cols(cols)
, m_step(orig.m_step)
, m_data(orig.m_data + orig.index(start_row, start_col))
{
assert(start_row+rows <= orig.m_rows && start_col+cols <= orig.m_cols);
}
};
原始矩阵构造函数假定它的backing
参数指向一个至少rows*cols
长的数据元素数组,用于存储矩阵数据。矩阵的维度由数据成员m_rows
和定义m_cols
。
数据成员m_step
表示从一行的开头到下一行的开头有多少个数据元素。对于原始矩阵,这与 相同m_cols
。请注意,m_cols
子矩阵的 可能小于它所指的原始矩阵的 —— 这就是子矩阵“跳过”原始矩阵中不属于子矩阵的元素的方式。为了使其正常工作,m_step
必须与原始矩阵中的相同。
不管矩阵是否跳过元素,数据成员m_data
总是指向矩阵的第一个元素。子矩阵构造函数中的assert()
确保每个新的子矩阵都适合它所派生的矩阵。
我不确定这是否算作“有趣的算法”,但它是定义和访问子矩阵的一种有效且方便的方法。