我有许多唯一的数字,都是正数,顺序无关紧要,0 < num < 2^32
示例:23 56 24 26
最大的56
需要6 bits
个空间。所以,我需要:4*6 = 24 bits
。
我执行以下操作以节省空间:
我先对它们进行排序:23 24 26 56
(因为顺序无关紧要)
现在我得到了前者的差异:23 1 2 30
最大的30
,需要5 bits
个空间
在此之后,我将所有数字存储在4*5 bits = 20 bits
空间。
问题:如何进一步改进此算法?
更多信息:根据要求,这些数字大多数位于2.000-4.000
范围内。小于300
的数字非常罕见。超过16.000
的数字也非常罕见。一般来说,所有数字都将接近。例如,它们可能都在1.000-2.000
范围内,或者它们都可能在16.000-20.000
范围内。数字总数将在500-5.000
范围内。
答案 0 :(得分:4)
您的第一步是好的,因为排序可以将差异减少到最少。这是一种改进算法的方法:
使用霍夫曼编码比你的步骤更重要;我会告诉你原因:
考虑以下数据:
1 2 3 4 5 6 7 4294967295
其中4294967295 = 2 ^ 32-1。使用您的算法:
1 1 1 1 1 1 1 4294967288
所需的总比特仍为32 * 8
使用霍夫曼编码,频率为:
1 => 7
4294967288 => 1
霍夫曼代码为1 => 0
和4294967288 => 1
所需的总位数= 7 * 1 + 1 = 8位
霍夫曼编码将大小减小32 * 8/8 = 32次
答案 1 :(得分:4)
这个问题在数据库社区中被称为“反向索引压缩”。你可以谷歌搜索一些文件。
以下是一些最常用的技术:
VByte和Simple9 / 16最容易实现,速度快,并且在实践中具有良好的压缩比。
霍夫曼编码对于索引压缩不是很好,因为它很慢并且差异在实践中是非常随机的。 (但在你的情况下,它可能是一个不错的选择。)
答案 2 :(得分:2)
你有多少个号码?如果你的集合覆盖范围[0..(2^32)-1]
足够密集(你做数学运算)那么4GiB位域,其中n
位表示自然数n
的存在或不存在可能有用。
答案 3 :(得分:0)
如果您的数字分布不均匀,则可以通过使用数字的频率来实现更好的压缩,并将更少的位数影响到最常用的位数。这是huffman coding背后的想法。