让我们假设我们有一个simmetric矩阵。
A=
1 2 3
2 6 4
3 4 5
现在,因为我们不需要存储记忆中的所有数字。我们假设将0放在左下三角的单元格中。
B =
1 2 3
0 6 4
0 0 5
如果我想访问B的0元素的内容,我需要做的就是反转感兴趣的单元格的行和列:
if(i>j) val += L[j][i] // ex: B[1][0] is stored in B[0][1]
(让我们假设目标是将所有非记忆元素相加)
此时我们只使用右上角三角形,但我们实际上并没有节省内存,因为未使用的元素仍然被赋值为0。
节省记忆的一种方法是使用矢量矢量:
vector<vector<int>> C;
并相应地调整每一行的大小。
C=
1 2 3
6 4
5
通过这样做很难,我们不能再使用交换技巧了,因为您可能会注意到空元素现在位于矩阵的右下角三角形中。
然后是未分配的值:
D=
x x x
x x 2
x 3 4
在这种情况下,我们感兴趣的元素可以通过以下条件找到:
if(j >= size - i)
现在的问题是识别0元素的正确内容。换句话说:
if(j >= size - i) ans += L[?][?]
所以例如,如果我在 i = 1 j = 2 我不应该访问元素[1] [2]而是访问[0] [2] = 2 (等等[2] [1] - &gt; [0] [2] = 3,[2] [2] - &gt; [1] [1] = 4)。
怎么可能实现呢?
答案 0 :(得分:0)
您可以通过存储左下角三角形并丢弃右上角三角形来解决特定问题:
1
2 6
3 4 5
索引操作可以实现为:
int operator()(int r, int c) const { return r >= c ? L[r][c] : L[c][r]; }
如果你真的想按照你的建议以变换的方式存储矩阵的右上角三角形(参见 C ),那么你可以访问矩阵元素:
int operator()(int r, int c) const { return c >= r ? L[r][c-r] : L[c][r-c]; }
但是,如果您真的想从压缩中获得一些利润,我建议将整个三角形打包在一个单维向量中。有向量的向量反而增加了相当大的开销......
答案 1 :(得分:0)
要在压缩的线性向量中存储这样的三角形数组,我使用以下类。
#define ogf_array_check(index, data_size) assert(index < data_size)
#define ogf_assert(b) assert(b)
/**
* A 2d array of values aij where only the cells such
* that j <= i are represented.
*/
template <class T> class TriangularArray {
public:
typedef TriangularArray<T> thisclass ;
TriangularArray(int size) : size_(size), data_size_(size * (size + 1) / 2) {
data_ = new T[data_size_] ;
}
~TriangularArray() { delete[] data_; data_ = nil ; }
int size() const { return size_ ; }
int data_size() const { return data_size_ ; }
/**
* index0 denotes the line, and index1 the column,
* note that index1 should be less-than or equal to
* index0.
*/
T& operator()(int index0, int index1) {
ogf_array_check(index0, size_) ;
ogf_array_check(index1, size_) ;
#ifdef OGF_ARRAY_BOUND_CHECK
ogf_assert(index1 <= index0) ;
#endif
int offset = index0 * (index0 + 1) / 2 ;
return data_[offset + index1] ;
}
/**
* index0 denotes the line, and index1 the column,
* note that index1 should be lerr or equal to
* index0.
*/
const T& operator()(int index0, int index1) const {
ogf_array_check(index0, size_) ;
ogf_array_check(index1, size_) ;
#ifdef OGF_ARRAY_BOUND_CHECK
ogf_assert(index1 <= index0) ;
#endif
int offset = index0 * (index0 + 1) / 2 ;
return data_[offset + index1] ;
}
void set_all(const T& value) {
for(int i=0; i<data_size_; i++) {
data_[i] = value ;
}
}
T& from_linear_index(int index) {
ogf_array_check(index, data_size_) ;
return data_[index] ;
}
const T& from_linear_index(int index) const {
ogf_array_check(index, data_size_) ;
return data_[index] ;
}
T* data() const { return data_ ; }
private:
T* data_ ;
int size_ ;
int data_size_ ;
private:
TriangularArray(const thisclass& rhs) ;
thisclass& operator=(const thisclass& rhs) ;
} ;