我用成员写了一个小的稀疏矩阵类:
std::map<int,std::map<int,double> > sm;
下面的方法是我用来访问矩阵元素的函数,如果通过迭代器不可能的话:
double matrix::operator()(int r,int c) const
{
std::map<int,std::map<int,double> >::const_iterator i = sm.find(r);
if(i==sm.end()) { return 0.0; }
std::map<int,double>::const_iterator j = i->second.find(c);
if(j==i->second.end()) { return 0.0; }
return j->second;
}
仍需要经常调用此函数。有人知道如何改进这个功能吗?谢谢。
答案 0 :(得分:5)
如果您要编写自己的代码而不是使用库,那么此更改可能会显着提高性能:
std::map<std::pair<int,int>, double> sm;
为了进一步增加,你可以去散列容器:
std::unordered_map<std::pair<int,int>, double> sm;
(使用tr1,boost或C ++ 0x)
编辑:在第一种情况下,您可以像这样迭代row
:
for(auto& cell : make_pair(
sm.lower_bound(make_pair(row, 0)), sm.lower_bound(make_pair(row+1, 0))))
{ ... }
如果您使用Boost.MultiIndex,我认为您可以通过使用适当的仿函数调用equal_range来完成上述操作。
超越一切:
for(auto& cell : sm)
{ ... }
迭代一列,您需要分别搜索每个单元格。请注意,您的数据结构也不提供此操作。
答案 1 :(得分:1)
你可能会讨厌这个,但对于以下(显示用途很小)矩阵行:
1 0 0 5 9 0 0 0
你可以有一个位数组(在这种情况下为8位),其中每个位被设置或清除以反映矩阵中该位置是否存在非零或零。
然后,您只需将非零数字存储在一起打包在一起的常规数组中,如:
{ 1, 5, 9 }
和二进制标志
0x98 //二进制1001 1000
要遍历矩阵行,您只需使用位操作来遍历位数组:
while (! /* not at the end of the bit array */ ) {
f = get_next_from_bit_array(); // This is just bitwise shift and bitwise &
if (!f) {
val = 0;
} else {
val = compressed_row[i];
i++;
}
do_action(val);
}
我的代码只是用于演示而不是C ++,但我希望你能得到这个想法。
使用位数组将允许您检查稀疏行的更小内存区域,这意味着更少的内存访问和更好的缓存局部性。
如果您使用的矩阵非常稀疏,那么您也可以将其扩展到另一个维度(具有稀疏的行数组),但是整行可能为空的可能性很低。