一种基于部分霍夫曼树的数据压缩编码方法
技术领域
本发明涉及数据压缩领域,更具体地涉及一种基于部分霍夫曼树的数据压缩编码方法,以通过构建部分霍夫曼树实现快速数据压缩编码的方法。
背景技术
随着计算机和网络技术的蓬勃发展,整个网络的数据量正呈指数型增长。虽然计算机的处理速度、硬盘容量以及网络带宽也有了巨大的进步,但仍难以适应数据增长的速度。如何将数据压缩的更小,压缩的更快一直以来都是人们积极研究的方向。
熵编码是数据压缩的一种重要方式。简单地说,熵编码的内涵就是对一段数据中出现概率高的字符用较短的码字代替,相应的较少出现的字符则用相对长的码字代替,这样就达到了对数据压缩的目的,所以熵编码可以看作是一个分配码字的过程。在由q个字符组成的字符集{a1,a2,…,aq}中,字符ai(i=1,2,…,q)发生的概率为pi,分配给它的编码长度为Li,最优编码便是指平均编码长度:
公式1
为最小的一种编码方案。
霍夫曼编码算法正是一种十分经典且有效的最优编码方法。具体来说,霍夫曼编码过程可以分为概率统计-生成编码表-编码三个步骤:即首先统计待编码数据中各个字符以及它们的出现概率;然后,依照每个字符出现概率的大小,应用霍夫曼编码算法为它们分配不同的码字,生成编码表;最后,对照编码表将原字符替换成相应的码字,即完成了对数据的编码。
在霍夫曼编码算法中,生成编码表是其算法的核心。编码表是一个待编码字符集{a1,a2,...,aq}与其码字集{s1,s2,...,sq}之间的映射关系表。在经典的霍夫曼编码方法中,主要依靠构建霍夫曼树来生成编码表。
霍夫曼树是一种典型的二叉树,在二叉树中节点由线段相互连接,这些线段叫做“枝”,处于“枝”上方的节点称为“父”,处在下方的节点称为“子”,处在整个树最上端的没有“父”的节点称为“根”,处在最下方的没有“子”的称为“叶子”。处在父节点右下方的所有子节点构成该节点的右子树,左下方的构成左子树。从根节点到达各个节点所经过的节点数称为该节点的路径长度,拥有相同路径长度的节点组成一个层。
现有的构建一棵霍夫曼树并生成编码表的主要步骤如下:
1)根据待编码字符集{a1,a2,...,aq}以及它们的概率{p1,p2,...,pq}构造二叉树集F:{T1,T2,...,Tq},其中,树Ti中仅有一个带权的根节点,且其概率等于相应字符ai的概率。
2)在树集F中找到两棵根节点概率最小的树,以它们作为左右子树构造一棵新的二叉树,新二叉树根节点的概率是其左右子树根节点概率的和。
3)在F中删除这两棵树,并将新的二叉树加入F。
4)重复步骤2)和3)直至F中仅剩一棵树为止,这棵树便是霍夫曼树。
5)自顶向下遍历整棵树,输出编码表。
这种经典的霍夫曼编码方法存在以下两个问题:
1)这种方法每次的递推过程都要进行大量的排序操作,在最终的霍夫曼树中所有节点都是按照顺序依次排列的,这种排列需要以大量的比较运算作为支撑,影响了整个算法的效率。
2)这种经典霍夫曼编码方法必须构建完整的霍夫曼树才能编码,理论研究表明,霍夫曼树中层间节点的关系以及层内节点的排序对于生成编码表并没有贡献。只要采用某种方法将待编码字符存入相应的层,即可实现最优编码。
发明内容
本发明的目的在于,提供一种部分霍夫曼树的构建方法及其快速数据压缩编码方法,该方法为仅构建霍夫曼树的一部分就能生成编码表的新方法,简言之,首先通过较为粗略但计算十分简便的方法为所有需编码的字符预先分配一个编码长度,从而构成一个分层的编码表称为预编码表;然后以预编码表为基础对霍夫曼树中一些特定部分进行构建;在构建部分霍夫曼树的同时,动态的调整字符的层序,实现对预编码表的修改,直到其满足了最优编码表的条件为止。这样不用构建一个完整的霍夫曼树,就能获得与经典霍夫曼算法同样的编码效果。
为实现上述发明目的,本申请的一种基于部分霍夫曼树的数据压缩编码方法,所述的编码方法包括步骤:
1)统计数据中各个字符的出现概率,得到字符集及与其相应的概率集。
2)对数据的字符集中的各个字符预先分配一个预编码长度,构成分层的预编码表。其中,所述的预编码表中每一层的字符拥有相同的编码长度,较低层字符的概率小于较高层字符的概率。该预编码表中相邻的两层之间有一个固定的概率边界,且相邻两个边界值为二倍关系。
3)以预编码表为基础自底向上的逐层构建部分霍夫曼树。在构建过程中,首先递推的计算各层的节点个数,如果一层中节点个数为偶数,则继续计算上一层的节点个数;如果一层中节点个数为奇数,需首先对该层节点个数偶数化,并动态调整字符的编码长度,同时更新编码表;如果调整后的编码表满足最优编码表的条件,则终止构建部分霍夫曼树,否则重复步骤3)继续计算上一层的节点个数。
其中,所述最优编码表的条件为:
公式2
式中,Li(i=1,2,…,q)为编码表中各个字符的编码长度。
4)以经过步骤3)修改后的预编码表为基础,采用范式霍夫曼的编码规范,输出最优编码表,用它对数据进行压缩编码。
步骤2)中所述的预编码表的建立方法包括步骤:
21)确定分层边界,规定第n层与第n-1层概率边界值为:Un=2-n+0.5,第n层与第n+1层概率边界值为:Un+1=2-n-0.5;
22)在字符集{a1,a2,...,aq}中若字符ai的概率pi满足Un<pi≤Un+1,则将ai填入预编码表的第n层。
所述的步骤3)中计算部分霍夫曼树中各层的节点个数的公式为:
Sn=Cn+Sn+1/2(n=1,2,…,M);公式3
其中,Sn为部分霍夫曼树中第n层的节点个数,Cn为预编码表中第n层的字符个数,M为最大层序。
所述的步骤3)中Sn为奇数时,对于部分霍夫曼树的第n层节点个数进行偶数化具体包括以下步骤:
31)找到第n层概率最大的节点Cmax与第n-1层概率最小的节点Cmin以及以它们为根节点的树Tmax和Tmin;
32)以这两棵树作为左右子树,构成一棵新树;
33)节点Cmax与节点Cmin的概率之和如果大于第n-1层的上界值,子树Tmax中的所有节点提升一层,否则就将子树Tmin中的节点下降一层;
34)找到被调整的子树Tmax或者Tmin中所含的叶子节点,更新预编码表中与其对应的字符层序。
所述的步骤31)中寻找Cmax、Tmax与Cmin、Tmin的具体步骤包括:
311)设定一个层序的中间变量p,初始值为p=M。
312)将第p层概率最大的2p-n个节点按概率大小顺序排列,依次作为左右子节点构建2p-n-1个新节点,新节点的概率等于其左右子节点概率的和;将这些新节点的概率逐个与编码表中第p-1层字符的概率进行比较,得到这两部分中概率最大的2p-n个节点。
313)类似于步骤312)将第p层概率最小的前2p-n+1个节点按概率大小顺序排列,依次作为左右子节点构建2p-n个新节点,新节点的概率等于其左右子节点概率的和;将这些新节点的概率逐个与编码表中第p-1层字符的概率进行比较,得到这两部分中概率最小的2p-n个节点。
314)如果p大于n,将p减1,重复执行步骤312)与步骤313);如果p等于n+1则输出第n层最大节点Cmax,并追溯该节点的构成,找出Tmax,将p减1,继续执行步骤313);如果p等于n则结束循环,输出Cmin并追溯该节点的构成,找出Tmin。
本发明的优点在于采用本发明可以有效的克服经典霍夫曼算法中影响运算效率的两个问题:
1)本发明通过计算字符的概率所处的范围就可预判其层序,在整个生成编码表的过程中,不必对所有的字符进行排序,从而减少了部分比较运算,缩减了计算量。
2)本发明仅通过构建霍夫曼树的一部分就能生成最优编码表。这样就消除了经典霍夫曼算法中的冗余计算,再次的缩减了计算量。
总之,采用本发明有效地消除了经典霍夫曼算法中的冗余计算,提高了编码效率,可作为通用算法,用于对数据的压缩编码,提高实时性。同时,降低对能源的消耗,尤其适用于能源受限的应用领域,如对海洋水声数据的采集与存储。
附图说明
关于本发明的操作方法和组织,及其目标、特征和优点等,当参照附图,阅读中可参考以下详细描述有助于更好地理解,在附图中:
图1是本发明的实例中寻找第三层概率最大节点过程的第一步的示意图。
图2是本发明的实例中寻找第三层概率最大节点过程的第二步的示意图。
图3是本发明的实例中第三层概率最大的节点以及其子树的示意图。
图4是本发明的实例中第二层概率最小的节点以及其子树的示意图。
图5是本发明的图3与图4中找到的两个子树合并的过程,以及所引发的对编码表的修改。
图6是在经典霍夫曼编码方法生成的霍夫曼树中,本发明生成的部分霍夫曼树所处的位置。
具体实施方式
以下结合实际例的具体实施方式,对本发明的上述内容再做进一步详细说明但不应将此理解为本发明上述主题的范围仅限于以下实例。在不脱离本发明上述思想的情况下,根据本领域普通技术知识和惯用手段做出的各种替换或者变更,均应包括在本发明内。
1.概率统计
扫描整个待编码数据,统计其中各个字符出现频率,通常一个字符可以是任意的,例如一个字节、一个报头、一个ASCII字符等等。统计过程无需对字符概率进行排序,直接生成一个无序的字符概率表。
2.预编码表的建立
建立预编码表有以下几个原则:
1)每一层的字符拥有相同的编码长度。
2)较低层字符的概率小于较高层字符的概率。
3)预编码表中相邻的两层之间有一个固定的概率边界,且相邻两个边界值为二倍关系。
由此得出一个较为简洁高效的建立预编码表的方法:
21)确定分层边界,规定第n层与第n-1层概率边界值为:Un=2-n+0.5,第n层与
第n+1层概率边界值为:Un+1=2-n-0.5。
22)在字符集{a1,a2,...,aq}中若字符ai的概率pi满足Un<pi≤Un+1则将ai填入预编码表的第n层。
23)确定预编码表总层数M与每一层的字符个数Cn(n=1,2,…,M)。
3.部分霍夫曼树的建立
生成了预编码表之后,接下来需通过建立部分霍夫曼树来将其调整为最优编码表。这个部分是本发明的关键。
建立一棵部分霍夫曼树是一个自底向上逐层递推的过程,具体可以分为以下几个步骤:
31)对中间变量进行初始化。该过程中主要涉及两个中间变量,一个是当前层的层序n,另一个是部分霍夫曼树当前层所含的节点总数Sn。设定初始层序n=M,初始的Sn=Cn,Sn+1=0。
32)检查编码表是否满足最优编码表条件。即是公式2是否成立。如果等式成立,直接转入第4步输出编码表。否则继续执行步骤33)。
33)计算部分霍夫曼树中第n层的节点数目。部分霍夫曼树中第n层所含的节点个数可根据公式Sn=Cn+Sn+1/2得出。
34)如果Sn为偶数,将层序减1,重复步骤33)继续计算上一层的节点个数。
如果Sn为奇数,需先对其字符个数偶数化并更新编码表,再将层序减1,跳转至步骤32)检查当前编码表是否满足最优编码表的条件。其中字符个数偶数化的具体方法又可分为如下几个步骤:
a)首先寻找第n层概率最大的节点Cmax与第n-1层概率最小的节点Cmin以及以它们为根节点的树Tmax和Tmin;其步骤如下:
i.设定一个层序的中间变量p,初始值为p=M。
ii.将第p层概率最大的2p-n个节点按概率大小顺序排列,依次作为左右子节点构建2p-n-1个新节点,新节点的概率等于其左右子节点概率的和;将这些新节点的概率逐个与编码表中第p-1层字符的概率进行比较,得到这两部分中概率最大的2p-n个节点。
iii.类似于步骤ii将第p层概率最小的前2p-n+1个节点按概率大小顺序排列,依次作为左右子节点构建2p-n个新节点,新节点的概率等于其左右子节点概率的和;将这些新节点的概率逐个与编码表中第p-1层字符的概率进行比较,得到这两部分中概率最小的2p-n个节点。
iv.如果p大于n,将p减1,重复执行步骤ii与步骤iii;如果p等于n+1,则输出第n层最大节点Cmax,并追溯该节点的构成,找出Tmax,将p减1,并执行步骤iii;如果p等于n则结束循环,输出Cmin并追溯该节点的构成,找出Tmin。
b)找到Tmax和Tmin后,以这两棵树作为左右子树,构成一棵新的树。
c)新树的根节点的概率(节点Cmax与节点Cmin的概率和)如果大于第n-1层的上界值Un-1,将节点Cmax提升到第n-1层,同时子树Tmax中的所有其他节点也随之提升一层。否则就将节点Cmin下降到第n层,同时子树Tmin中的其他节点也随之下降一层。
d)找到被调整的子树Tmax或者Tmin中所含的叶子节点,更新编码表中与其对应的字符层序。
4.输出编码表
对于编码表的输出,主要用到了范式霍夫曼编码的编码规范,仅根据预编码表中各个字符的编码长度直接输出最优编码表。最后根据最优编码表对数据进行编码。
实施例
1.随机选取一段英文文本并对其中出现的英文字符进行统计,表1为各个字符出现次数的统计结果。
表1字符出现次数统计表
字符 |
出现次数 |
“H” |
8 |
“M” |
10 |
“A” |
11 |
“Q” |
3 |
“K” |
9 |
“F” |
10 |
“D” |
11 |
“C” |
5 |
“N” |
5 |
“B” |
7 |
“P” |
4 |
“E” |
11 |
“Y” |
4 |
“S” |
2 |
2.依据预编码方法,计算各层间的概率边界,将字符按照其概率所处的范围分入相应层,生成如表2所示的预编码表。
3.由表2可知,预编码表共有五个层,其中各层字符个数为,C5=4、C4=4、C3=6,其余层字符个数为0。
表2预编码表
4.接下来开始构建部分霍夫曼树。
1)首先检验预编码表是否直接满足最优编码表条件,即对于所有的字符等式是否成立,其中Li(i=1,2,…,14)为字符的编码长度。结果为该预编码表不满足,故继续构建部分霍夫曼树。
2)预编码表共有5个层,设定层序初始值n=5,节点个数初始值S6=0。编码表中第5层的字符数C5=4,故S5=C5+S6/2=4,为偶数。依照生成部分霍夫曼树的步骤,将层序n减1,继续计算第4层的节点个数。
3)更新层序后,继续带入公式S4=C4+S5/2,此时预编码表的第4层仍然有4个字符所以C4=4,得到S4=6。部分霍夫曼树第4层的节点数仍然为偶数,故将层序n再次减1,计算第3层的节点个数。
4)对于第3层,C3=6,S3=C3+S4/2=9。此时节点个数首次为奇数,需对其偶数化:
a)首先要找到第3层概率最大的节点和第2层概率最小的节点以及以它们为根的子树。
i.为找到第3层概率最大的节点要从第5层概率最大的4个节点开始比较,它们分别是节点P(0.04)、节点Y(0.03)、节点Q(0.03)、节点S(0.03),括号中是它们的概率。将这4个节点按顺序排列,两两作为左右子节点结合生成新的节点。新节点的概率分别为0.07和0.06。称它们为节点“0.07”和节点“0.06”,如图1所示,图中左部为编码表的图示,表中字符用方块表示,方块内括号中的数字为该字符的概率。右侧为部分霍夫曼树,对于与编码表中的字符相对应的叶子节点,与编码表采用相同的表示方式。对于没有字符与其对应的中间节点则直接用圆圈和其概率表示,如节点“0.07”。
ii.将步骤i生成的这两个新节点与第4层概率最大的两个节点:节点H(0.08)、节点B(0.07)的概率进行比较。找出四个节点中概率最大的两个节点,分别为节点H(0.08)和节点“0.07”,它们结合后新的父节点的概率为0.15,即节点“0.15”,如图2所示。
iii.编码表中第3层概率最大字符为“D”,其概率为0.11。故第3层中概率最大的节点为节点“0.15”。
iv.节点“0.15”由节点H(0.08)与节点“0.07”构成,而节点“0.07”又由节点P(0.04)和节点Y(0.03)构成。由此可知以节点“0.15”为根的子树的结构,如图3所示。
v.同样的方法,可以计算出第2层概率最小的节点为节点“0.19”,该节点由第3层的节点F(0.1)和节点K(0.09)构成。如图4所示。
b)接下来将两个子树合并。合并后产生的新树根节点的概率为0.34,小于第2层的概率上界U3=2-1.5=0.35,所以需将以节点“0.19”为根节点的子树中所有的节点下降一层。
c)在以节点“0.19”为根节点的子树中包含了两个叶子节点,节点K(0.10)和节点F(0.09)。需在编码表中将与它们相对应的字符也下降一层,它们在编码表中的对应字符“K”和字符“F”由第3层下降到了第4层,如图5所示,右侧为合并后的部分霍夫曼树,左侧图示了合并导致的对编码表的更改。
5)再次检验最优编码表条件。条件成立,即对于分配给每个字符的编码长度Li有
停止构建部分霍夫曼树。
5.依据范式霍夫曼编码的规定,编码表中第3层的第一字符“D”编为000,第二个字符“M”编为000+1=001。以此类推,第3层的最后一个字符的编码为011,故第4层的第一个字符编为(011+1)*2=1000。全部的编码如表3所示,括号中为该字符的编码。最后,根据以上步骤得到的最优编码表,直接对数据进行压缩编码。
表3最终编码表
第3层 |
D(000) |
M(001) |
A(010) |
E(011) |
|
|
第4层 |
H(1000) |
C(1001) |
N(1010) |
B(1011) |
K(1100) |
F(1101) |
第5层 |
P(11100) |
Q(11101) |
Y(11110) |
S(11111) |
|
|
该实例如果采用经典霍夫曼编码方法,生成的霍夫曼树,如图6所示,其中深色部分为采用本发明算法是所需构建的部分霍夫曼树。可见同样为获得最优编码表,采用本发明的方法仅需构建原有算法中霍夫曼树的一部分,所以采用本发明的方法来生成编码表能够有效地节省计算量,消除原算法中的冗余操作,提高了算法效率。
最后,根据以上步骤得到的最优编码表,直接对数据进行压缩编码。
最后所应说明的是,以上实施例仅用以说明本发明的技术方案而非限制。尽管参照实施例对本发明进行了详细说明,本领域的普通技术人员应当理解,对本发明的技术方案进行修改或者等同替换都不脱离本发明技术方案的精神和范围,其均应涵盖在本发明的权利要求范围当中。