如何有效地查找大型std :: map

时间:2016-12-11 06:28:32

标签: c++ c++11

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

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

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

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

&#34; mapIntVecOfInts2&#34;映射&#34; mapIntVecOfInts1&#34;中存在的VALUES;到另一组价值观。例如

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

现在我要映射&#34; mapIntVecOfInts1&#34;中存在的键。到#34; mapIntVecOfInts2&#34;中出现的值使用来自&#34; mapIntVecOfInts1&#34;的传递映射; to&#34; mapIntVecOfInts2&#34;。例如。我想为关键&#34; 0&#34;做以下事情。 mapIntVecOfInts1:

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

&#34; mapIntVecOfInts1&#34;和&#34; mapIntVecOfInts2&#34;包含十亿个元素(键)。两个映射中的向量本身包含百万个无符号整数。我尝试通过存储&#34; mapIntVecOfInts1&#34;来实现两个地图之间的这种传递闭包。和&#34; mapIntVecOfInts2&#34;在记忆中。使用以下代码:

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

然而,以这种方式执行传递闭包需要花费很多时间。有什么方法可以加快这个速度。

2 个答案:

答案 0 :(得分:2)

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

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

生成的映射将具有与第一个关系完全相同的键集,因此您可以(通过先复制整个mapIntVecOfInts1然后修改值来避免整个红黑树构建过程)副本而不是逐个添加向量。

当然,这不会解决主要的瓶颈,即第二关系的访问速度(mapIntVecOfInts2)。您可以尝试使用哈希表(std::unordered_map)将其减少为摊销的O(1),或者如果您的&#34;十亿的键&#34;不是太稀疏。

同样@SpectralSequence说,你的代码不保留值向量中的唯一性,也许你想对此做些什么。

答案 1 :(得分:1)

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

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

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