如何有效地查找大向量中的元素

时间:2015-05-27 10:19:45

标签: c++ c vector

我的vector<unsigned>大小为(90,000 * 9,000)。我需要多次查找此向量中是否存在元素?

为此,我使用std::sort()将矢量存储在已排序的表单中,然后使用std::binary_search()在向量中查找元素。但是在使用perf进行性能分析时,我发现在vector<unsigned>中查找元素是最慢的操作。

有人可以在data-structure中建议一些C/C++,我可以用它来有效地查找(90,000 * 9,000)元素向量中的元素。

我只进行一次插入(批量插入)。剩下的时间我只执行查找,所以这里的主要开销是因为查找。

4 个答案:

答案 0 :(得分:10)

你有40亿个可能值中的8.1亿个值(假设32位unsigned)。这是总范围的1/5,使用3.2 GB。这意味着你实际上对于具有40亿位的std::vector<bool>更好。这样可以在更小的空间(0.5 GB)内进行O(1)查找。

(理论上,unsigned可能是16位。unsigned long 至少 32位,std::uint32_t可能是你想要的那样)

答案 1 :(得分:3)

根据向量的实际数据结构,contains操作可能需要O(n)O(1)。通常,如果vector由关联数组或链表支持,则为O(N),在这种情况下,contains将在最坏的情况下进行完整扫描。您已通过订购和使用二进制搜索(O(log (N)))来减轻完整扫描。 Log N非常复杂,只有O(1)更好。所以你的选择是:

  • 缓存查找项目的结果,如果您有多次重复相同的元素,这可能是一个很好的折衷方案
  • 使用高效contains操作替换另一个数据结构的向量,例如基于hashtableset的操作。请注意,您可能会遗漏其他功能,例如订购商品
  • 使用两个数据结构,一个用于contains操作,另一个用于
  • 的原始向量
  • 使用提供折衷的第三种数据结构,例如与bloom filter配合良好的数据结构

答案 2 :(得分:2)

  

然而,在使用perf进行分析时,我发现在中查找元素   矢量是最慢的操作。

这是您需要的一半信息,另一半是 &#34;与其他算法/容器相比有多快&#34; ?也许使用std::vector<>实际上是最快的,也可能是最慢的。要找到你,必须对一些不同的设计进行基准测试。

例如,以下是在1000x9000大小的容器上使用随机整数的非常天真的基准测试(我会在地图的较大尺寸上获得seg-fault,可能是32位内存的限制)。

如果您需要非唯一整数的计数:

  • std::vector<unsigned> = 500毫秒
  • std::map<unsigned, unsigned> = 1700 ms
  • std::unordered_map<unsigned, unsigned> = 3700毫秒

如果您只需要测试是否存在唯一整数:

  • std::vector<bool> = 15 ms
  • std::bitset<> = 50 ms
  • std::set<unsigned> = 350毫秒

请注意,我们对确切的值不太感兴趣,而是对容器之间的相对比较感兴趣。 std::map<>相对较慢,考虑到所涉及的数据的动态分配和非本地化的数量,这并不奇怪。如果需要非唯一整数的计数,那么位集是迄今为止最快的但不起作用。

我建议使用您确切的容器尺寸和内容来做类似的基准测试,这两者都可能影响基准测试结果。事实证明std::vector<>可能是最好的解决方案,但现在你有一些数据来支持这种设计选择。

答案 3 :(得分:1)

如果你不需要遍历集合(以排序的方式),因为c ++ 11你可以使用std::unordered_set<yourtype>,你需要做的就是提供获取散列的集合方式和{的相等信息{1}}。访问集合元素的时间在这里分摊为O(1),与排序向量不同,其中它是O(log(n))。