我正在使用gnu ++ 0x中的std::unordered_map
来存储大量数据。我想为大量元素预先分配空间,因为我可以限制使用的总空间。
我希望能够做的是致电:
std::unordered_map m;
m.resize(pow(2,x));
其中x是已知的。
std::unordered_map
不支持此功能。如果可能的话,我宁愿使用std::unordered_map
,因为它最终会成为标准的一部分。
其他一些限制:
需要可靠的O(1)访问和地图变异。期望的散列和比较函数已经是非标准的并且有些昂贵。 O(log n)突变(与std::map
一样)太昂贵了。
- >昂贵的哈希和比较也使基于摊销的增长方式过于昂贵。每个额外插入都需要来自这些函数的O(n)运算,这会在算法的运行时间内产生额外的二次项,因为指数存储需求需要O(n)增长。
答案 0 :(得分:31)
m.rehash(pow(2,x));
如果pow(2, x)
是您想要预先分配的存储区数量。你也可以:
m.reserve(pow(2,x));
但现在pow(2, x)
是您计划插入的元素数量。这两个函数除了预分配桶之外什么都不做。它们不插入任何元素。它们都可以完全用于您的用例。
注意:您不能保证获得完全pow(2, x)
个桶。一些实现将仅使用多个桶,其是2的幂。其他实现将仅使用素数桶。还有一些人将仅使用素数的子集来表示桶的数量。但无论如何,实现应该接受你想要的桶数提示,然后在内部向上舍入到下一个可接受的桶数。
以下是最新的(N4660)用于指定rehash
的参数的准确措辞:
a.rehash(n)
:后置条件: a.bucket_count() >= a.size() / a.max_load_factor() and a.bucket_count() >= n
。
此后置条件可确保bucket()_count() >= n
和load_factor()
保持小于或等于max_load_factor()
。
后来reserve(n)
是根据rehash(n)
:
a.reserve(n)
:与a.rehash(ceil(n / a.max_load_factor()))
相同。
答案 1 :(得分:5)
我认为无序地图有预先分配的内存并不重要。预计STL将是O(n)摊销的插入时间。在我看来,除非你知道这是代码的瓶颈,否则请自己省去编写自己的分配器的麻烦。
答案 2 :(得分:3)
我建议为std::unordered_map
编写自己的分配器,以完全按照你想要的方式分配内存。
答案 3 :(得分:1)
构造函数采用参数" size_type bucket_count"根据{{3}}
因此,执行示例代码所说的最简单的方法是:
std::unordered_map m{ pow(2,x) };
这样会更有效率,因为它未定义在构造上将保留多少桶,否则它可能必须分配,然后在您之后调用reserve时释放。
答案 4 :(得分:-2)
我认为 rehash 和 reserve 只有在事先知道映射值需要多少内存时才会起作用。如果映射的值很复杂或动态地改变大小(例如向量),则需要您自己的实现。例如,如果您的内存大小允许,您可以保留可能存在的最大容器。