整数下限和上限查询的快速数据结构?

时间:2012-01-31 19:16:54

标签: c++ data-structures stl integer set

我必须保留一个数字列表,数量最多为100,000 ......

如果数据是(例如)

1, 4, 9, 12, 20, 35, 52, 77, 91

我查询一个数字,比方说27,我想要的数字就在27之前,可以在列表中找到,所以这将是:20

数据也会经常被修改,比如大量的插入和删除。

目前我正在使用stl::set加上

set<int>iterator it = lower_bound(values.begin(), values.end(), n);

所以

*it = 35 使用it--,我得到20 ......但这还不够快,查询的数量很大,最多可达500,000 ..其中包括更改我的值或查找值。

请给我一些指示。

3 个答案:

答案 0 :(得分:6)

想到了一些不同的想法。

对于初学者来说,有一个专门的数据结构正是这个问题称为van Emde Boas tree,它将整数存储在某个固定范围[0,U]中,并支持O(log log U)时间内的后继和前任搜索。这比使用标准二叉搜索树进行比较要快得多。如果您知道要存储的整数的上限,则此结构可能会使您获得更高的性能。还有其他相关的结构,如y-fast trie也可以在这里使用。

其次,如果您拥有的查询是统一分布的,您可能需要构建自己的二进制搜索树,该搜索树已经过优化,可以最大限度地减少整体查找的节点数。这种搜索树被称为最优二叉搜索树,并且存在用于在O(n log n)时间内近似它们的快速算法。在this earlier question中,我详细介绍了一种方法。这种预处理可以为您提供更快的查找速度,因为树是专门为优化查找时间而构建的。或者,您可以查看splay trees,它可以提供相当的性能。

希望这有帮助!

答案 1 :(得分:0)

您可以将所有数字除以(例如)100个向量

1-> [0..99]
2-> [100..199]
.....

应该对这些向量进行排序。使用lower_bound / upper_bound函数在向量上搜索通常比在关联容器中更快。但是对于插入或删除,您需要使用一个小向量。

UPD 我同意templatetypedf:van Emde Boas树可能是更好的解决方案。

答案 2 :(得分:0)

100,000足够小,以至于我只考虑使用位向量... 100,000位只有12.5K,搜索速度非常快,甚至可以适合L1缓存。

向后存储位(即100000靠近结尾; 0靠近开头),这样你在内存中的扫描是线性的,你可以使用ffs(如果你的平台有它)。