紧凑的数据结构,用于存储大量的整数值

时间:2011-03-08 23:23:13

标签: c# algorithm data-structures

我正在开发一个需要传递大量Int32值的应用程序。这些集合应包含~1,000,000-50,000,000个项目,其中每个项目都是0-50,000,000范围内的数据库密钥。我希望任何给定集合中的id分布在这个范围内是有效随机的。我需要的操作很简单:

  • 添加新值
  • 迭代所有值。

对这些集的内存使用情况存在严重担忧,因此我正在寻找一种能够比简单List<int>HashSet<int>更有效地存储ID的数据结构。我看过BitArray,但这可能是浪费,取决于ID的稀疏程度。我也考虑过按位trie,但我不确定如何计算该解决方案对预期数据的空间效率。如果我能忍受假阴性,那么Bloom Filter会很棒。

对于适合此目的的数据结构的任何建议,我将不胜感激。我对开箱即用和自定义解决方案感兴趣。

编辑:回答您的问题:

  • 不,不需要对项目进行排序
  • 通过“传递”我的意思是在方法之间传递序列化并通过线路发送。我显然应该提到这一点。
  • 同时在内存中可以有相当数量的这些集合(~100)。

3 个答案:

答案 0 :(得分:5)

使用BitArray。它只使用大约6MB的内存;唯一真正的问题是迭代是Theta( N ),即你必须遍历整个范围。引用的位置很好,您可以在一次操作中分配整个结构。

至于浪费空间:在最坏的情况下你会浪费6MB。

编辑:好的,你有很多套,而且你正在序列化。对于在磁盘上序列化,我建议6MB文件:)

要通过电汇发送,只需迭代并考虑发送范围而不是单个元素。这确实需要一个排序结构。

你需要很多这些套装。考虑一下你是否有600MB备用。否则,请查看:

  • Bytewise尝试:O(1)插入,O( n )迭代,比按位尝试低得多的常数因子
  • 自定义哈希表,可能是Google sparsehash到C ++ / CLI
  • BST存储范围/间隔
  • Supernode BSTs

答案 1 :(得分:1)

我认为答案取决于你的意思是“四处传播”以及你想要完成的事情。你说你只是添加到列表中:你多久添加一次?这个名单的增长速度有多快?与重新分配内存的时间相比,内存使用的可接受开销是多少?

在最糟糕的情况下,使用最有效的数据存储机制,5​​0,000,000个32位数= 200 MB。假设你可能在最糟糕的情况下最终使用这么多东西,那么可以一直使用这么多内存吗?这比经常重新分配内存更好吗?典型使用模式的分布是什么?你总是可以使用预先分配给整个5000万的int[]

就操作的访问速度而言,没有什么比迭代和添加到预先分配的内存块更快。

从OP编辑:一次可以在内存中有相当数量的这些集(~100)。

嘿,现在。您需要一次在内存中存储100组1到5千万个数字吗?我认为bitset方法是唯一可行的方法。

那将是600兆字节。并非无足轻重,但除非它们(通常)大部分都是空的,否则您似乎不太可能找到更有效的存储机制。

现在,如果你不使用bitsets,而是使用动态大小的结构,并且它们可能以某种方式开始占用更少的空间,那么你谈论的是一个真正丑陋的内存分配/释放/垃圾收集场景。 / p>

让我们假设您真的需要这样做,尽管我只能想象为什么。所以你的服务器有大量的内存,只需根据你的需要分配这些6兆字节的位数就可以回收它们。分配和垃圾收集不再是问题。是的,你使用了大量的记忆,但这似乎是不可避免的。

答案 2 :(得分:1)

这取决于套装尺寸的分布。除非你期望大多数集合(接近)你指定的最小值,否则我可能会使用bitset。为了覆盖高达50,000,000的范围,bitset最终会达到~6兆字节。

与直接存储数字相比,对于您指定的最小尺寸设置(~6 MB而不是〜4)略大,但对于最大尺寸设置(1/32 nd <)则要小得多/ sup>大小)。

第二种可能性是使用增量编码。例如,不是直接存储每个数字,而是存储该数字与包含的前一个数字之间的差异。如果最大幅度为50,000,000,最小尺寸为1,000,000个项目,则一个数字与下一个数字之间的平均差异为~50。这意味着理论上你可以平均存储差值<6位。我可能直接使用7个最低有效位,如果你需要编码更大的间隙,设置msb和(例如)将间隙的大小存储在低7位加上接下来的3个字节中。这通常不会发生非常,因此在大多数情况下,每个数字只使用一个字节,与直接存储数字相比,压缩比约为4:1。在最好的情况下,对于一个集合,这将使用~1兆字节,而在最差的情况下,与直接存储数字相比,最差的约为50兆字节--4:1压缩。

如果您不介意一些额外的代码,您可以使用自适应方案 - 针对小型集合(最多6,000,000个数字)的delta编码,以及针对较大集合的位图。

相关问题