一种快速解析码长的哈夫曼解码方法
技术领域
本发明涉及一种解码方法,尤其涉及一种快速解析码长的哈夫曼解码方法。
背景技术
哈夫曼算法是一种根据待压缩数据中各元素出现的概率进行编码和解码的算法,能无损的压缩数据所占用的空间。图1是一个哈夫曼码字生成树的例子,以其码字为叶子,码字所属层数为级别数。
解析哈夫曼码时,先确定要解析的码流的首个码字长度,将其取出,用哈夫曼编码提供的符号表就可以找到这个码字所对应的数据元素。除去码流里的首个码字,将剩余的码流按上述方法逐一解析,即可完成哈夫曼的解码过程。由于哈夫曼编码是变长编码,在整个解码过程中,必须解决的一个问题是确定哈夫曼码字的长度,以下描述了哈夫曼解码中码字长度确定的常见解决方案。
A、逐位比较解析法:将哈夫曼码字所有级别的首个码字按级别为索引建立一张码长检索表。解码时,取出码流里的第一个比特,如果这个码流数值不小于码长为1的码长检索表所对应的码字,将前面取出的比特数左移一位,并加上下一个取出的比特数,将这个合成的码流数值与上一个码长加1所对应的码长检索表中的哈夫曼码字比较;如果这个新的码流数值还是不小于新的哈夫曼码字,继续按上述方法比较,直到码流数值小于码长检索表中的哈夫曼码字。那么,这个哈夫曼码字所对应的码长减1就是码流里首个哈夫曼码字的长度。
B、级别比较解析法:由于哈夫曼码字生成树并不一定每一级都有叶子,对于那些叶子不存在的级别还去比较就没有意义。级别比较解析法正是基于这一点,在逐位比较解析法的基础上,用一个叶子检索表来指示最近下一级存在哈夫曼码字的级别(等同码字长度),并将同一级上最小码字作为前缀位,其余位补0,扩充到最大码长长度,用这个扩充码建成一张定长码字检索表。在哈夫曼码长解析时,取出码流中待解码的最大码长长度的码流数值与定长码字检索表里的首个码字比较,如果这个码流数值不小于定长码字检索表里的码字,按照叶子检索表检索当前级别的下一级叶子码字级别,然后用这个下一级别值来检索定长码字检索表里的码字,以码流数值比较检索到的定长码字,直到码流数值小于定长码字检索表里的码字,此时叶子检索表里当前级别数和码流里首个码字长度相同。
在音频、视频领域,基于哈夫曼数据压缩的编码、解码算法应用非常广泛。在哈夫曼算法中,码字以变长二进制前缀码表示,为了解析一个哈夫曼码字,必须先解析哈夫曼码字的字长,传统的码长解析算法在总的解码算法中耗时比例较大,减少码长解析的时间对于提高哈夫曼解码的速度有很重要的意义。
发明内容
本发明目的在于提供一种可以快速解析码长的哈夫曼解码方法。
本发明的目的可以通过以下技术实现:一种快速解析码长的哈夫曼解码方法,步骤包括:
1)基于码流中所包含的所有哈夫曼码字生成树的叶子码字,建立一张完备码长码表;
2)对于当前待解析的哈夫曼码流,按照其待解析码字所属的哈夫曼码字生成树,在定长码字完备码长码表中检索到与这个哈夫曼码字生成树相对应的码表部分;
3)以最大码字长度截取当前待解析的哈夫曼码流,并将这个截取出的码流数值作为索引,在当前码流哈夫曼码字生成树对应的码长码表部分检索,检索到的当前码长码表值即为当前待解析码流中首个码字码长;
4)提取首个码字,在当前哈夫曼码字生成树所对应的符号表中即可解析到当前码字所对应的数据;从码流中除去已解析的部分,将剩余码流返回第二步;直至全部码流解析完毕后退出。
上述的构造哈夫曼码字生成树对应的完备码长码表的过程:
按照对应的哈夫曼码字生成树,构建最大码长长度的各个比特位为全0到全1的索引,并将所有索引值(即码长码表值)初始化为0;以哈夫曼生成树的所有叶子码子为前缀,将剩余码字位以全0到全1填充到最大码长长度,将所有同哈夫曼码字前缀的扩充码的码长码表值以对应哈夫曼前缀码的长度赋值。
上述的完备码长码表的每项索引以哈夫曼码字为前缀、其余位按全0到全1填充扩展到最大码长长度,索引对应的值为相应的哈夫曼前缀码码长。
本发明可以根据索引快速解析码长,从而大大减少解码时间,当最大码长为N时,对于逐位比较解析法,解析其码长时间复杂度为o(N/2);对于级别比较解析法,解析其码长时间复杂度为o
其中p
i为码长为i的码字的统计概率;本发明将所有码长以码字为索引建成一张表,那么对于一个给定的码字,其码长解析时间复杂度为o(1),极大地提高码长确定速度。
说明书附图
图1是现有技术中哈夫曼码字生成树;
图2是本发明单个哈夫曼码字生成树对应码长码表的生成流程。
具体实施方式
首先构建一张以哈夫曼码字为定长码前缀的完备码表:这个完备码长码表的每项索引以哈夫曼码字为前缀、其余位按全0到全1填充扩展到最大码长长度,索引对应的值为相应的哈夫曼前缀码码长。在这个完备码长码表的构建过程中,以码流包含的每个哈夫曼码字生成树为单位,按相同的方式逐一构建。
图2是码长码表构建过程中单个哈夫曼码字生成树对应部分的处理,其中当前级别、当前叶子数和当前码字在当前级别中的位序均从0起始。初始化将所有码长设为0,并设置当前级别为1;每个哈夫曼码字生成树对应的码长码表部分构建过程如下,
1)提取当前级别的首个哈夫曼码作为前缀,获得以首个哈夫曼码为前缀的8比特码字总数;然后设置当前级别当前叶子位序为0;
2)令当前码字的值为前缀码补0到定长加上当前叶子位序,然后设置当前叶子当前码字位序位0;
3)设置当前码字对应的码长为当前级别值,并当前码字加1;
4)比较当前码字位序是否小于当前码字总数,如果结果返回是,则码字位序加1并返回步骤4;如果结果返回否,则进行下一步;
5)将前缀码加1作为下一个前缀码,比较当前叶子位序是否小于级别总叶子数,如果结果返回是,则当前叶子位序加1并返回步骤3;如果结果返回否,则进行下一步;
6)检测当前码字级别是否不大于8,如果结果返回是,则返回步骤2;如果结果返回否,则码表生成完毕并结束。
然后对于当前待解析的哈夫曼码流,按照其待解析码字所属的哈夫曼码字生成树,在定长码字完备码长码表中检索到与这个哈夫曼码字生成树相对应的码表部分。
以最大码字长度截取当前待解析的哈夫曼码流,并将这个截取出的码流数值作为索引,在当前码流哈夫曼码字生成树对应的码长码表部分检索,检索到的当前码长码表值即为当前待解析码流中首个码字码长。
提取首个码字,在当前哈夫曼码字生成树所对应的符号表中即可解析到当前码字所对应的数据。从码流中除去已解析的部分,剩余码流返回继续解析,直至完成所有哈夫曼码的解析。
假设当前待解析码流为11010011111……,其最大码长为5,对应的哈夫曼码字生成树和图1相同,码流解析过程如下。以5截取码流,得到11010,以11010为索引在码长码表中查得对应的哈夫曼码字长度为4,并查得码字1101在符号表中对应的符号,从码流中除去1101,即完成一个哈夫曼码字解析。同理,可解析到码字00、11111……。