这些点表示道路网络。它们是固定点4字节整数对XXXXYYYY的形式。通常,如果单个数据块有100个点,则X和Y的前两个字节将只有几个组合(空间相关性)。但底部字节始终在变化,必须对zlib看起来像随机数据。
同样,记录具有4字节ID,其倾向于具有恒定的高字节和可变的低字节。
是否有另一种算法能够更好地压缩这种数据?我正在使用C ++。
编辑:请不要再建议更改数据本身。我的问题是关于自动压缩算法的。如果有人有所有流行压缩算法概述的链接,我会接受它作为答案。
如果您根据数据结构进行压缩,那么您很可能会得到更好的结果。
通用压缩算法只是将您的数据视为位流。它们寻找常用的位序列,并用较短的字典索引替换它们。
但是重复的数据并没有消失。重复的序列变短了,但是它仍然像以前一样经常重复出现。
据我所知,您有大量的数据点采用以下格式:
XXxxYYyy,其中大写字母非常统一。因此,请将它们分离出来。
将列表重写为类似于以下内容:
XXYY // a header describing the common first and third byte for all the subsequent entries
xxyy // the remaining bytes, which vary
xxyy
xxyy
xxyy
...
XXYY // next unique combination of 1st and 3rd byte)
xxyy
xxyy
...
虽然不是针对你的数据,但如果可以的话,我建议你使用7zip而不是zlib。 我曾经看到过使用它时非常好的压缩比率。
通过某种接近度量对点进行排序,使相邻点之间的平均距离较小。然后存储相邻点之间的差异。
如果您设法将点排序,使大多数差异在x和y轴上都是正的,那么效果可能会更好,但我不能确定。
作为zlib的替代方案,一族压缩技术通用编码在概率分布偏向小数时表现良好。它们必须针对有符号数字进行调整(编码abs(x)<<1 + (x < 0 ? 1 : 0)
)。
没有看到数据及其确切分布,我无法确定最佳方法,但我建议您在每组1-4条记录中以一个字节开始,该字节的8位指示以下内容:
0-1 从上一条记录中借用的ID字节数 2-4 位置记录格式 6-7 使用相同“模式”字节的后续记录数
每个位置记录可以以八种方式之一存储;除了000类型之外的所有类型都使用有符号位移。位码后面的数字是位置记录的大小。
000 - 8 - 两个完整的四字节位置 001 - 3 - 十二位X和Y 010 - 2 - 十位X和六位Y 011 - 2 - 六位X和十位Y 100 - 4 - 两个十六位有符号位移 101 - 3 - 十六位X和8位Y有符号位移 110 - 3 - X为8位有符号位移;Y为16位 111 - 2 - 两个八位有符号位移
模式字节为零将存储所有适用于点的信息,而不参考任何先前的点,使用总共13个字节来存储12个字节的有用信息。其他模式字节将允许根据与先前记录的相似性来压缩记录。如果四个连续记录仅在ID的最后一位上不同,并且X和Y都在前一个记录的+/- 127范围内,或者X在+/- 31范围内,Y在+/- 511范围内,或者X在+/- 511范围内,Y在+/- 31范围内,则所有四个记录可以存储在13个字节中(平均每个记录3.25个字节(空间减少了73%)。
可以使用“贪心”算法进行压缩:检查记录以查看输出中将使用哪个大小的ID和XY,然后获取多达三个记录,直到找到一个记录,该记录无法使用所选大小与先前记录“匹配”,或者可以更小地编写(请注意,例如,如果第一条记录的X和Y位移都等于12,则XY将用两个字节编写,但是在读取以下记录之前,人们不知道要使用哪种两个字节格式中的哪一个)。
在确定你的格式之前,我建议你先将数据运行一遍。也许只需要进行小的调整(例如使用7+9或5+11位格式而不是6+10),就可以更好地压缩许多数据。然而,真正了解情况的唯一方法是查看实际数据的效果。看起来Burrows-Wheeler transform可能对这个问题有用。它有一个奇特的倾向,将重复字节的运行放在一起,这可能使zlib压缩更好。这篇文章建议我应该将BWT与除zlib以外的其他算法结合使用。
直觉上听起来很昂贵,但是查看一些源代码后发现,反向BWT是O(N),需要对数据进行3次传递和适度的空间开销,可能足够快地在我的目标平台(WinCE)上运行。正向变换大约是O(N log N)或略高,假设使用普通排序算法。
你可能想要将两个列表写入压缩文件:一个 NodeList
和一个 LinkList
。每个节点都会有一个 ID、x 和 y 坐标。每个链接都会有一个 FromNode 和 ToNode,以及一系列中间 xy 值的列表。你可以使用带有虚假原点的标题记录,并使节点 xy 值相对于该原点。
如果您的街道遵循城市网格网络,则这将提供最大的好处,通过消除交叉口处的重复坐标。
如果不需要无损压缩,则可以使用截断的增量来表示中间坐标。虽然上面有人提到了增量,但请记住,连接性的丢失可能会比形状的丢失更容易引起问题,如果您使用截断的增量来表示道路的最后一个坐标(通常是交叉口),那么就会发生这种情况。
同样,如果您的道路不在城市网格上,则可能不会带来太多好处。