我有x(百万)个正整数,其值可以大到允许的值(+2,147,483,647)。假设它们是唯一的,那么将它们存储为查找密集型程序的最佳方法是什么。
到目前为止,我想到了使用二进制AVL树或哈希表,其中整数是映射数据(名称)的关键。但是我不确定我是否可以使用哈希表来实现如此大的密钥(除了容易发生冲突之外,不会创建> 0.8的加载因子吗?)
我能否就哪种数据结构适合我的情况得到一些建议
答案 0 :(得分:6)
结构的选择在很大程度上取决于你有多少可用内存。我假设你根据描述你需要查找但不要循环它们,找到最近的或其他类似的操作。
Best可能是一个分段哈希表。通过将哈希冲突放入存储桶并在存储桶中为密钥和值保留单独的数组,您既可以减小表的大小,又可以在搜索存储桶时利用CPU缓存加速。桶内的线性搜索甚至可能比二进制搜索更快!
AVL树适用于读取密集但不是只读的数据集,需要有序的枚举,查找最近和类似的操作,但它们是正确实现的烦人工作量。但是,由于CPU缓存行为,您可能会使用B树获得更好的性能,尤其是缓存无关的B树算法。
答案 1 :(得分:2)
log_m(n)
和log_(m/2)(n)
之间运行,因此,如果您选择m
大约为8-10左右,则应该能够将搜索深度保持在10以下。
答案 2 :(得分:2)
位向量,如果存在数字,则设置索引。您可以调整它以获得每个数字的出现次数。 Bentley'编程珍珠中有一个很好的关于位向量的专栏。
答案 3 :(得分:1)
如果记忆不是问题,地图可能是你最好的选择。地图是O(1)意味着当您向上扩展要查找的项目数时,查找值的时间是相同的。
键是int的映射,值是名称。
答案 4 :(得分:0)
首先尝试哈希表。有一些变种可以容忍非常密集而没有明显的减速(如布伦特的变化)。
如果您只需要存储32位整数而不是任何相关记录,请在大多数C ++库中使用set
而不是map
,如hash_set
。它将仅使用4字节记录加上一些常量开销和一点松弛以避免100%。在最坏的情况下,要处理'数百万'的数字,你需要几十兆字节。很大,但没什么难以管理的。
如果你需要它更紧凑,只需将它们存储在一个普通的数组中,并使用二进制搜索来获取它们。它将是O(log n)而不是O(1),但对于'数百万'的记录,它仍然只是二十几步来获得它们中的任何一个。在C中你有bsearch()
,它的速度最快。
编辑:只是在你的问题中看到你谈到一些'映射数据(一个名字)'。那些名字是独特的吗?他们还必须留在记忆中吗?如果是的话,他们肯定会主导内存要求。即便如此,如果名称是典型的英语单词,大多数将是10个字节或更少,使总大小保持在“几十兆字节”;也许高达一百兆,仍然非常易于管理。