如何有效地查找元素在一个大的向量
How to efficiently look up elements in a large vector
我有一个大小为(90,000 * 9,000)
的vector<unsigned>
。我需要多次查找一个元素是否存在于这个向量中?
为此,我使用std::sort()
以排序形式存储向量,然后使用std::binary_search()
查找向量中的元素。然而,在使用perf
进行分析时,我发现查找vector<unsigned>
中的元素是最慢的操作。
有人可以建议一些C/C++
中的data-structure
,我可以用它来有效地查找(90,000 * 9,000)
元素向量中的元素。
我只执行一次插入(大容量插入)。其余时间我只执行查找,所以这里的主要开销是查找。
您已经获得了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
可能是你想要的)
根据向量的实际数据结构,contains
操作可以是O(n)
或O(1)
。通常,如果vector由关联数组或链表支持,则为O(N)
,在这种情况下,contains
在最坏的情况下将是完全扫描。您已经通过排序和使用二进制搜索(O(log (N))
)减轻了完全扫描。Log N
是相当好的复杂度,只有O(1)
更好。所以你的选择是:
- 缓存查找结果的项目,这可能是一个很好的妥协,如果你有许多重复的相同的元素
- 将vector替换为其他具有高效
contains
操作的数据结构,例如基于散列表或集合的数据结构。注意,您可能会丢失其他功能,例如物品订购 - 使用两种数据结构,一种用于
contains
操作,另一种用于 的原始向量 - 使用提供折衷的第三种数据结构,例如与布隆过滤器工作良好的数据结构
然而,在使用perf进行分析时,我发现在Vector是最慢的操作
这是你需要的一半信息,另一半是"与其他算法/容器相比,它有多快"?也许使用std::vector<>
实际上是最快的,或者可能是最慢的。为了找到答案,你必须对几个不同的设计进行基准测试/配置文件。
如果你需要一个非唯一整数的计数:
-
std::vector<unsigned>
= 500 ms -
std::map<unsigned, unsigned>
= 1700 ms -
std::unordered_map<unsigned, unsigned>
= 3700 ms
如果您只需要测试是否存在唯一整数:
-
std::vector<bool>
= 15 ms -
std::bitset<>
= 50 ms -
std::set<unsigned>
= 350 ms
请注意,我们对容器之间的相对比较不太感兴趣,而是对容器之间的确切值感兴趣。std::map<>
相对较慢,考虑到动态分配的数量和所涉及的数据的非局部性,这并不奇怪。bitset是迄今为止最快的,但如果需要非唯一整数的计数,则不起作用。
我建议使用您确切的容器大小和内容进行类似的基准测试,这两者都可能影响基准测试的结果。std::vector<>
可能是最好的解决方案,但现在你有一些数据来支持这个设计选择。
如果自c++11以来您不需要迭代集合(以排序的方式),您可以使用std::unordered_set<yourtype>
,您需要做的就是为yourtype
提供获取哈希和相等信息的集合方式。访问集合中元素的时间平摊为O(1),不像排序向量的时间是O(log(n))
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 为什么一个向量上的多线程操作很慢
- 将一个向量插入另一个向量的某个位置
- 将指向给定子类的指针从一个向量复制到另一个向量
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 将向量之间的数字放在另一个向量之间<vector>>如果两个数字的差值为 1
- 如何在不复制的情况下将一个向量移动到另一个向量中
- 使用 std::transform 将向量向量 (a) 添加到另一个向量向量 (b)
- 如何按另一个向量的方向调整一个向量?
- 将字符向量复制到另一个向量
- 制作一对共享指针并推送一个向量
- 你能把一个向量<int64>投射到一个向量<uint8>吗
- 大家好,当一个类有一个向量作为它的数据成员时,为什么它的大小总是24?
- 为什么我们需要在优先级队列声明中添加一个向量作为参数?
- 如何将所有指针从一个向量移动到另一个向量?
- 将一个向量映射到不同的对,即使向量映射到每对时是不同的?
- 生成一个类Name_class并将两种数据类型存储在一个向量中
- 使用步骤c++构建一个向量
- 如何从另一个向量中的另一个第一元素减去向量中的第一元素
- 将一个向量对放在一个无序映射与一个映射中