我的vector<unsigned>
大小为(90,000 * 9,000)
。我需要多次查找此向量中是否存在元素?
为此,我使用std::sort()
将矢量存储在已排序的表单中,然后使用std::binary_search()
在向量中查找元素。但是在使用perf
进行性能分析时,我发现在vector<unsigned>
中查找元素是最慢的操作。
有人可以在data-structure
中建议一些C/C++
,我可以用它来有效地查找(90,000 * 9,000)
元素向量中的元素。
我只进行一次插入(批量插入)。剩下的时间我只执行查找,所以这里的主要开销是因为查找。
答案 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
操作替换另一个数据结构的向量,例如基于hashtable或set的操作。请注意,您可能会遗漏其他功能,例如订购商品contains
操作,另一个用于答案 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))。