首先,我要说我只有基本的压缩知识。
我怀疑Deflate算法的工作分辨率不低于字节,即用字节数据查找重复,构建Haffman树等。为了证明这一点,我写了以下代码:
http://dotnetfiddle.net/iuxE5H
简而言之,该代码创建了一个100,000位的序列,它由两种方式表示:第一个是平凡的表示(每个字节包含8位),第二个是间隔很大的表示 - 每位字节(每个字节为0或1) ,这意味着所有7个MSB都是0)。使用大量重复创建数据以证明两种情况下的压缩效果。我认为间隔表示(每比特字节)应该不比普通表示(每字节8比特)差,因为Deflate算法应该找到大量重复的0x00和0x01。
令人惊讶的是,在短的重复序列(50-100位)中,结果是相似的,这意味着Deflate确实找到了重复的子字节序列。令人惊讶的是,在较长的重复序列(500-1,000位)中,非间隔位表示的结果更好,因为通过找到0x00和0x01重复,Deflate算法非常无效!
所以第一个问题是:为什么Deflate无法找到那些重复?
这是问题的背景,以及此后的另一个问题。
背景
我正在尝试找到一个紧凑的表示数据结构。这是一种类似四叉树的结构,是某种算法的输出。表示有两部分:结构(节点/叶子)和数据本身。这个问题涉及第一部分的表示 - 数据结构的结构。
使用以下形式的递归算法在服务器端创建结构:
INode CreateSubTree(input)
{
if (mathematical-condition)
return new Leaf(...);
INode left = CreateSubTree(sub-input);
INode right = CreateSubTree(sub-input);
return new Composite(left, right);
}
在数据结构紧凑表示中,我按照它们计算的相同顺序保存数学条件的日志(每个日志项为真/假)。然后在客户端,我可以回收确切的结构,而不需要所有的数学数据。
表示的第二部分是节点的数据。由于我已经有了这个结构,我只需要按照明确定义的顺序保存原始数据,而不需要将它与节点相关联,客户端就能将数据与节点相关联。
最后的表示是将两个部分写入流中,然后使用Deflate算法(通过.NET的DeflateStream类)在发送到客户端之前对其进行压缩。
问题:
虽然数据有很多重复序列,但结构中的条件日志具有高水平的熵,而Deflate算法对该部分无效。紧凑的表示非常重要,因此我正在寻找减少表示大小的方法。这也是上面讨论的位/字节调查的原因。
所以第二个问题是:有人能想出更好的方法来紧凑地表示这样的结构吗?