【问题标题】:How to efficiently look-up large std::map如何有效地查找大型 std::map
【发布时间】:2016-12-11 06:28:32
【问题描述】:

我想执行 2 个大键值列表的传递闭包。为此,我有两个“std::map”。 std::map 都将整数映射到整数向量。

std::map<unsigned,vector<unsigned> > mapIntVecOfInts1; 
std::map<unsigned,vector<unsigned> > mapIntVecOfInts2;

"mapIntVecOfInts1" 将键映射到另一组键(值)。其中的一些示例值具有以下形式:

0 -> (101, 102, 201)
1 -> (101, 102, 103, 203, 817, 1673)
2 -> (201, 829, 858, 1673)

“mapIntVecOfInts2”将“mapIntVecOfInts1”中存在的值映射到另一组值。例如

101 -> (4002, 8293, 9000)
102 -> (4002, 8293, 10928)
103 -> (8293, 10928, 19283, 39201)
201 -> (8293)
203 -> (9393, 9830)
817 -> (19393, 19830) 
1673-> (5372, 6830)

现在我想使用从“mapIntVecOfInts1”到“mapIntVecOfInts2”的传递映射将“mapIntVecOfInts1”中存在的键映射到“mapIntVecOfInts2”中存在的值。例如。我想对 mapIntVecOfInts1 的键“0”执行以下操作:

0 -> 4002, 9000, 10928, 8293, 19283, 39201
1 -> 4002, 8293, 9000, 10928, 19283, 39201, 9393, 9830, 19393, 19830, 5372, 6830

“mapIntVecOfInts1”和“mapIntVecOfInts2”包含十亿个元素(键)。两个映射中的向量本身包含数百万个无符号整数。我尝试通过在内存中存储“mapIntVecOfInts1”和“mapIntVecOfInts2”来执行两个映射之间的传递闭包。使用以下代码:

std::vector<unsigned,vector<unsigned> > result;
for(std::map<unsigned,vector<unsigned> >::iterator i1= mapIntVecOfInts1.begin(), l1=mapIntVecOfInts1.end(); i1!=l1;++i1)
{
    vector<unsigned> vec1;
    for(vector<unsigned>::iterator i2=(*i1).second.begin(), l2=(*i1).second.end(); i2!=l2; ++i2)
         vec1.insert(vec1.begin(), mapIntVecOfInts2[*i2].begin(), mapIntVecOfInts2[*i2].end());

     result.push_back(make_pair((*i1).first, vec1));
}

但是,以这种方式执行传递闭包会花费大量时间。有什么方法可以加快速度。

【问题讨论】:

  • 鉴于您的每张地图都有十亿个带有unsigned 键的条目,您为什么不使用vector 而不是map?即使在 64 位系统上,您的映射也很少稀疏。
  • @Peter 谢谢彼得,我尝试使用向量和 std::lower_bound 进行查找,但仍然需要相当长的时间
  • @Peter 他要么必须对向量进行排序,要么实现自己的二进制搜索。 (假设他需要随机查找,他可能不需要。)
  • 它并不是真正的“传递闭包”,更像是“关系的组合”
  • @AlexanderFell 但这仍然需要相当长的时间 -- 请发布您用于构建应用程序的编译器选项。如果构建未优化或“调试”构建,请构建优化的发布版本并重新测试。为调试或未优化的应用程序计时是没有意义的。

标签: c++ c++11


【解决方案1】:

可以说您建议的代码做了两件事:

  • 将第二个关系映射到第一个的条目
  • 根据所述映射的结果建立新关系

生成的映射将具有与第一个关系完全相同的键集,因此您可以(有点)通过先复制整个 mapIntVecOfInts1 然后修改复制而不是一个一个添加向量。

当然,这不会解决主要瓶颈,即您的第二个关系 (mapIntVecOfInts2) 的访问速度。如果您的“十亿键”不是太稀疏,您可以尝试使用哈希表 (std::unordered_map) 甚至向量将其减少到摊销 O(1)。

正如@SpectralSequence 所说,您的代码没有保留值向量中的唯一性,也许您想对此做点什么。

【讨论】:

    【解决方案2】:

    至少,您应该在内循环中插入向量的末尾,因为在开头插入需要复制向量中已经存在的元素。

    vec1.insert(vec1.end(), mapIntVecOfInts2[*i2].begin(), mapIntVecOfInts2[*i2].end());
    

    另外,如果您不想重复值,请考虑使用集合。

    【讨论】:

      猜你喜欢
      • 2010-09-10
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 2011-06-16
      • 1970-01-01
      相关资源
      最近更新 更多