如果没有重复,则可以有效地将整数插入到不断增长的数组中

Efficiently insert integers into a growing array if no duplicates

本文关键字:插入 整数 不断增长 数组 有效地 如果没有      更新时间:2023-10-16

有一个数据结构,它的作用就像一个不断增长的数组。当且仅当这些整数在此数据结构中没有重复时,将逐个向其中插入未知数量的整数。

最初我认为std::set就足够了,它会随着新整数的到来而自动增长,并确保没有重复。

但是,随着集合越来越大,插入速度也会下降。那么,除了哈希,还有其他做这项工作的想法吗?

Ps

我想知道像xor所有元素或构建稀疏表(就像rmq一样)这样的技巧会适用吗?

如果你愿意在这个问题上花费内存,2^32位就是512MB,这时你可以只使用一个位字段,每个可能的整数一位。抛开CPU缓存效应不谈,这就给出了O(1)的插入和查找时间。

如果不了解更多关于您的用例的信息,很难说这是一次值得使用的内存,还是一次几乎没有收益的巨大内存开销。

此站点包括所有可能的容器,并为每个操作安排运行时间,所以也许这将是有用的:

http://en.cppreference.com/w/cpp/container

似乎无序设置是你最好的方式。

您可以尝试std::unordered_set,它应该实现为哈希表(嗯,我不明白为什么要写"additional hash";std::set通常实现为平衡树,这应该是插入性能不足的原因)。

如果数字在某个范围内,则可以创建多个std::set作为bucket。

EDIT-根据您指定的范围,std::set应该足够快。O(logn)在大多数情况下都足够快,除非你已经进行了一些测量,并发现它在你的情况下很慢。

此外,您还可以将鸽子洞原理与sets一起使用,以拒绝任何可能的重复(适用于集变大时)。

位向量可用于检测重复

为了做出最佳决策,甚至需要更多的需求。此建议基于以下限制:Alcott 32位整数,约有10.000.000个元素(即2^32中的任何10m)

它是一个BST(二进制搜索树),每个节点存储两个值,即连续区域的开始和结束。第一个元素存储一个区域开始的数字,第二个元素存储最后一个。这种安排允许大区域,希望你能用很小的树高达到10M的极限,这样搜索就很便宜了。具有10m元素的数据结构每个节点将占用8个字节,加上每个节点最多两个子节点的链路(2x4字节)。因此,所有10M元素都有80M。当然,若通常插入了更多的元素,那个么您可以跟踪一次并没有插入的元素。现在,如果你需要非常小心空间,并且在运行模拟和/或统计检查后,你发现有很多小区域(长度小于32位),你可能需要将节点类型更改为一个开始区域的数字,再加上一个位图。

如果你不必对位图的访问进行对齐,比如说,你只有只有8个元素的连续块,那么你的备忘录要求是节点使用4+1,子节点使用4+4字节。希望这能有所帮助。