链式哈希表和理解Deflate

时间:2011-07-26 14:14:23

标签: c# algorithm compression

我目前正在尝试在C#中创建自定义Deflate实现。

我目前正在尝试实现“模式搜索”部分,我有(最多)32k的数据,并且我正在尝试为我的输入搜索最长的模式。

定义Deflate的RFC 1951说明了该过程:

  

压缩器使用链式哈希表来查找重复的字符串,      使用对3字节序列进行操作的散列函数。在任何      在压缩期间给定点,让XYZ成为接下来的3个输入字节      进行检查(当然不一定都是不同的)。首先,      压缩器检查XYZ的哈希链。如果链是空的,      压缩器只是将X写为文字字节并前进一个      输入中的字节。如果哈希链不为空,则表明      序列XYZ(或者,如果我们运气不好,还有其他3个字节      最近发生了相同的哈希函数值)压缩器      将XYZ哈希链上的所有字符串与实际输入数据进行比较      序列从当前点开始,并选择最长的序列      匹配。

我知道哈希函数是什么,并且知道HashTable是什么。但什么是“链式哈希表”以及如何将这样的结构设计为高效(在C#中)处理大量数据?不幸的是,我不明白RFC中描述的结构是如何工作的。

我可以选择什么样的哈希函数(什么才有意义)?

提前谢谢!

2 个答案:

答案 0 :(得分:3)

链式哈希表是一个哈希表,它存储您放入其中的每个项目,即使两个项目的密钥哈希值相同,或者即使两个项目具有完全相同的密钥。

DEFLATE实现需要以特定顺序存储一堆(密钥,数据)项,并快速查找具有该密钥的所有项的列表。 在这种情况下,密钥是3个连续字节的未压缩明文,数据是某种指针或偏移到明文中出现3字节子字符串的位置。

许多散列表/字典实现都存储了每个项目的密钥和数据。 没有必要将密钥存储在DEFLATE表中,但除了在压缩期间使用稍多的内存外,它不会造成任何损害。

某些散列表/字典实现(例如C ++ STL unordered_map坚持认为它们存储的每个(键,数据)项必须具有唯一键。当您尝试使用与表中已有的旧项相同的键存储另一个(键,数据)项时,这些实现将删除旧项并将其替换为新项。 那个受到伤害 - 如果你不小心使用了C ++ STL unordered_map或类似的实现,你的压缩文件会比使用更合适的库(如C ++ STL {{更大)。 1}}。 这样的错误可能难以检测,因为所得到的(不必要的大)压缩文件可以被任何标准DEFLATE压缩器正确解压缩到与原始文件相同的文件。 DEFLATE和其他压缩算法的一些实现故意使用这样的实现,故意牺牲压缩文件大小以获得压缩速度。

正如Nick Johnson所说,标准“哈希表”或“词典”实现中使用的默认哈希函数可能已经足够了。

http://en.wikipedia.org/wiki/Hashtable#Separate_chaining

答案 1 :(得分:2)

在这种情况下,他们描述了一个哈希表,其中每个元素都包含一个字符串列表 - 在这种情况下,所有字符串都以指定的三个字符前缀开头。您应该只需使用标准的.net哈希表或字典原语 - 无需复制其确切的实现细节。

32k并不是很多数据,因此您不必担心扩展哈希表 - 即使您这样做,内置基元也可能比您自己编写的任何内容都更有效。