【发布时间】:2017-06-13 01:55:34
【问题描述】:
正如标题所说,我正在寻找将集合存储在内存中的最佳方式。我只对字节集感兴趣(从0 到255 的整数数组,其中顺序并不重要)。不要求编码/解码速度很快。唯一需要的是集合应该需要尽可能少的内存。
我想出的第一个方法是为每个集合分配256 位数组(32 字节),n 位置的位告诉集合中是否有n。这种方法的问题在于,即使集合大部分是空的(只有很少的元素),它也需要相同数量的内存。
我尝试的第二种方法是将集合存储为常规数组。因此,如果一个集合包含n 元素,那么它将需要存储n + 1 字节。第一个字节表示元素的数量,其他字节表示元素。但是,正如我们所知,集合中的顺序并不重要,所以有些东西强烈地告诉我,必须有一种方法来改善这一点。
我的第三次尝试是枚举所有可能的集合并只存储集合的索引(整数表示它在所有可能的字节集合列表中的索引)。但是,事实证明它与第一种方法完全等价。基本上,我仍然需要32 字节来存储任何集合,所以它不是很有用。
我的第四次尝试是基于我的第二种方法。我注意到该集合包含n 元素,当然,它需要n + 1 字节(如果我使用第二种方法)。但是,例如,如果元素 k 出现在集合中(实际上是在数组中,因为在我的第二次尝试中我将集合存储为数组),那么它就不能再次出现。基本上,如果k 再次出现,那么它一定意味着不同的东西(可能是k - 1)。所以,我做了一些优化,我注意到如果我对每个下一个元素进行不同的编码,我可以节省一些字节(例如,[3, 3, 5, 7] 被解释为元素为{3, 4, 5} 的一组3 元素(每个下一个元素减少它的索引)和[3, 3, 5, 6]被解释为{3, 4, 2}(注意3和4已经存在,所以6减少2变成4,但是4存在并且@ 987654346@ 存在,所以它必须是2))。但是这种方法如何才能真正节省字节呢?我进行了实验并意识到我可以对数组中的元素进行排序,以便在某些情况下避免使用高位对元素进行编码,因此我为每个元素保存了 1 位,大约节省了 n / 16 字节(这是n / 2 * 1 / 8)。
我提出的第五种方法与我的第二种方法相似,但它对数字 fo 元素的解释不同。如果元素的数量小于128,那么它通常会从内存中的以下数组中读取所有元素。但是,如果元素的数量大于128,那么它会创建一个完整的集合,然后从内存中的以下数组中删除元素。平均而言,它节省了很多字节,但距离最优还差得很远。
我的最后一次尝试(第六次尝试)是仅枚举一些集合(例如,创建一个集合列表,其中将包含:完整集合、仅包含偶数的集合、仅包含奇数的集合、包含小于 128 个元素的集合、设置大于 128 的元素等),然后使用该列表中的元素和基本集合操作(联合、交集等)来重建原始集合。对于我们从列表中使用的每个基本集,它将需要几个字节,并且需要几个位来进行联合或交集操作,当然还有一个字节来表示序列的长度。这很大程度上取决于基本集合列表中应该硬编码的元素数量,但似乎很难预先创建和正确选择该列表中的元素。不管怎样,有件事告诉我这不是很聪明的方法。
但是帽子实际上是最优化的方式?有人告诉我,我的第四次尝试并没有那么糟糕,但我们能做得更好吗?我使用的集合具有随机数量的元素,因此平均每个集合有128 个元素,所以我正在寻找一种方法来为每个集合分配128 位(16 字节)。到目前为止,我做得最好的是使用离我的目标很远的第四种方法。
再次提一下,速度并不重要。编码/解码可能非常慢,唯一重要的是集合需要尽可能少的内存。当我说“在内存中”时,我的意思是在内存中编码(压缩)。此外,我对尽可能少的位(不仅仅是字节)感兴趣,因为我想在我的 HDD 上存储数十亿个压缩集,因此计算每个集所需的平均位数很重要,这样我就知道有多少资源可用于我想要实现的目标。
附:如果你想要一些代码(但我真的不明白你为什么要这样做),我可以在这里发布我用 C 语言为所有这些方法制作的解决方案。无论如何,我不是在询问如何在特定的编程语言中实现这一点的代码或技术细节,我只是在询问用于压缩集合的方法/算法。
提前谢谢你。
【问题讨论】:
-
你知道集合大小的分布吗?你似乎觉得大多数套装都很小;是这样吗,还是你只是认为你应该能够在小系列上做得更好,即使它们很少见?
-
集合中是否存在任何偏差,即某些值或值组合是否比其他值更可能出现?
-
您如何计算“2^256 位”相当于 32 个字节?它比那个大很多......稍后的“2^128 位”也是如此。
-
@rici。元素的数量是随机分布的。对于
0 - 255中的每个数字n,一个集合包含n元素的概率相同。我不认为具有 “更少元素” 的集合应该需要更少的内存。但是,平均而言,应该可以不为每个集合使用32位。 -
@m69。不幸的是没有。元素和元素数量是随机分布的。
标签: c arrays algorithm set compression