【问题标题】:Choosing a Data structure for very large data为非常大的数据选择数据结构
【发布时间】:2011-05-14 20:19:47
【问题描述】:

我有 x(百万)个正整数,它们的值可以尽可能大(+2,147,483,647)。假设它们是独一无二的,那么为查找密集型程序存储它们的最佳方式是什么。

到目前为止,我一直在考虑使用二叉 AVL 树或哈希表,其中整数是映射数据的键(名称)。但是我不确定我是否可以使用哈希表实现如此大的键和如此大的数量(除了容易发生冲突之外,这不会创建 >0.8 的负载因子吗?)

我可以就哪种数据结构可能适合我的情况获得一些建议

【问题讨论】:

  • 您是否要将整个结构保存在内存中?数据库通常使用 B-tree 进行这种搜索。该结构存储在磁盘上,即使索引中有大量键,也只需少量访问即可找到所需键。
  • @JOTN:CPU 缓存行填充对性能的影响与数据库页面读取的效果相同,尽管是微秒而不是毫秒。
  • 如果你打算使用自平衡树,那么我强烈建议你阅读这篇论文:web.stanford.edu/~blp/papers/libavl.pdf

标签: performance data-structures hashtable lookup avl-tree


【解决方案1】:

位向量,如果数字存在,则设置索引。您可以对其进行调整以获取每个数字的出现次数。 Bentley 的 Programming Pearls 中有一个关于位向量的不错的专栏。

【讨论】:

    【解决方案2】:

    你研究过 B 树吗?效率在log_m(n)log_(m/2)(n) 之间运行,因此如果您选择m 大约为8-10 左右,您应该能够将搜索深度保持在10 以下。

    【讨论】:

    • 不应该选择m在8-10左右而不是n吗?
    【解决方案3】:

    请先尝试哈希表。有一些变体可以容忍非常密集而不会显着减速(如布伦特变体)。

    如果您只需要存储 32 位整数而不需要任何关联的记录,请使用 set 而不是 map,如大多数 C++ 库中的 hash_set。它将仅使用 4 字节的记录加上一些恒定的开销和一点松弛以避免 100%。在最坏的情况下,要处理“数百万”个数字,您需要几十兆字节。很大,但没有什么不可管理的。

    如果您需要更紧凑,只需将它们排序存储在一个普通数组中,然后使用二进制搜索来获取它们。这将是 O(log n) 而不是 O(1),但对于“数百万”条记录,获取其中任何一条记录仍然只需要 20 多步。在 C 语言中,您有 bsearch(),它是最快的。

    编辑:刚刚在您的问题中看到您谈到了一些“映射数据(名称)”。这些名字是独一无二的吗?他们也必须在记忆中吗?如果是,它们肯定会主导内存需求。即便如此,如果名称是典型的英文单词,大多数会是 10 字节或更少,总大小保持在“数十兆字节”;可能高达一百兆,仍然非常易于管理。

    【讨论】:

      【解决方案4】:

      结构的选择很大程度上取决于您有多少可用内存。我假设您需要查找但不循环它们、查找最近的或其他类似操作的描述。

      最好的可能是分桶哈希表。通过将哈希冲突放入存储桶并在存储桶中为键和值保留单独的数组,您既可以适当地减小表的大小,又可以在搜索存储桶时利用 CPU 缓存加速。桶内的线性搜索甚至可能比二分搜索更快!

      AVL 树非常适合读取密集型但不是只读且需要有序枚举、查找最近和类似操作的数据集,但要正确实施它们需要大量工作。但是,由于 CPU 缓存行为,您可能会使用 B-tree 获得更好的性能,尤其是缓存忽略 B-tree 算法。

      【讨论】:

        【解决方案5】:

        如果内存不是问题,地图可能是您最好的选择。地图是 O(1),这意味着当您扩大要查找的项目数量时,查找值所需的时间是相同的。

        键是int,值是名称的映射。

        【讨论】:

        • 不要粗鲁什么的,但我假设他的桌子很稀疏,那不需要大量的内存吗?
        • 哦,当然,这会占用大量内存。但我确实用“如果记忆不是问题”来限定那句话......只是一个想法。
        • 如何计算我需要的内存量,在这种情况下,您的实现将占用多少内存。有没有办法计算?
        • 你所说的地图是指一些(变体)位向量(在这种情况下)吗?我真的想不出任何其他有保证的 O(1) 结构。具体来说,不是由树实现的地图。
        • 地图的意思是有键和记录的东西。即使是线性搜索的列表也符合要求。您可能在谈论哈希表或某些库中已知的“哈希映射”。
        猜你喜欢
        • 1970-01-01
        • 2011-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-13
        • 2014-05-16
        相关资源
        最近更新 更多