更有效的稀疏矩阵元素访问器

时间:2010-10-01 19:19:49

标签: c++ stl map sparse-matrix

我用成员写了一个小的稀疏矩阵类:

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;
}

仍需要经常调用此函数。有人知道如何改进这个功能吗?谢谢。

2 个答案:

答案 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 ++,但我希望你能得到这个想法。

使用位数组将允许您检查稀疏行的更小内存区域,这意味着更少的内存访问和更好的缓存局部性。

如果您使用的矩阵非常稀疏,那么您也可以将其扩展到另一个维度(具有稀疏的行数组),但是整行可能为空的可能性很低。