正如我在评论中提到的,使用向量的向量表示矩阵是不切实际的,原因如下:
- 设置很繁琐;
- 很难改变;
- 缓存位置不好。
这是我创建的一个非常简单的类,它将在单个向量中保存一个 2D 矩阵。这几乎就是 MATLAB 之类的软件的工作方式......尽管是一个巨大的简化。
template <class T>
class SimpleMatrix
{
public:
SimpleMatrix( int rows, int cols, const T& initVal = T() );
// Size and structure
int NumRows() const { return m_rows; }
int NumColumns() const { return m_cols; }
int NumElements() const { return m_data.size(); }
// Direct vector access and indexing
operator const vector<T>& () const { return m_data; }
int Index( int row, int col ) const { return row * m_cols + col; }
// Get a single value
T & Value( int row, int col ) { return m_data[Index(row,col)]; }
const T & Value( int row, int col ) const { return m_data[Index(row,col)]; }
T & operator[]( size_t idx ) { return m_data[idx]; }
const T & operator[]( size_t idx ) const { return m_data[idx]; }
// Simple row or column slices
vector<T> Row( int row, int colBegin = 0, int colEnd = -1 ) const;
vector<T> Column( int row, int colBegin = 0, int colEnd = -1 ) const;
private:
vector<T> StridedSlice( int start, int length, int stride ) const;
int m_rows;
int m_cols;
vector<T> m_data;
};
这个类基本上是围绕一个单一功能的糖衣—— StridedSlice
. 它的实现是:
template <class T>
vector<T> SimpleMatrix<T>::StridedSlice( int start, int length, int stride ) const
{
vector<T> result;
result.reserve( length );
const T *pos = &m_data[start];
for( int i = 0; i < length; i++ ) {
result.push_back(*pos);
pos += stride;
}
return result;
}
其余的非常简单:
template <class T>
SimpleMatrix<T>::SimpleMatrix( int rows, int cols, const T& initVal )
: m_data( rows * cols, initVal )
, m_rows( rows )
, m_cols( cols )
{
}
template <class T>
vector<T> SimpleMatrix<T>::Row( int row, int colBegin, int colEnd ) const
{
if( colEnd < 0 ) colEnd = m_cols-1;
if( colBegin <= colEnd )
return StridedSlice( Index(row,colBegin), colEnd-colBegin+1, 1 );
else
return StridedSlice( Index(row,colBegin), colBegin-colEnd+1, -1 );
}
template <class T>
vector<T> SimpleMatrix<T>::Column( int col, int rowBegin, int rowEnd ) const
{
if( rowEnd < 0 ) rowEnd = m_rows-1;
if( rowBegin <= rowEnd )
return StridedSlice( Index(rowBegin,col), rowEnd-rowBegin+1, m_cols );
else
return StridedSlice( Index(rowBegin,col), rowBegin-rowEnd+1, -m_cols );
}
请注意,Row
andColumn
函数的设置方式使您可以轻松地请求整行或整列,但功能更强大一些,因为您可以通过传递一个或两个更多参数来分割范围。是的,您可以通过使起始值大于结束值来反向返回行/列。
这些函数中没有内置边界检查,但您可以轻松添加它。
您还可以添加一些东西以将区域切片作为另一个返回SimpleMatrix<T>
。
玩得开心。