随心所“语”之huffman编码

    huffman编码、压缩,曾经写过一次,感觉很痛苦;最近,学习数据结构,又试了一次,感觉好多了。这里写下,总结下。

    huffman编码、压缩,我觉得主要两件事情:1、对字符生成对应的huffman编码;2、对数据进行huffman压缩。这些书本、网络介绍的太多了(比如:http://coolshell.cn/articles/7459.html),而且也很容易理解,我这里简单的讲下:将要压缩的数据进行遍历、统计;根据统计结果创建huffman树;根据huffman树,得到每个字符的huffman编码。

    对数据进行huffman压缩。有了huffman编码,那么再遍历一遍要压缩的数据,那么一一对应到每一个编码,那么就可以得到每一字符的huffman编码,写文件就可以了,完成huffman压缩了。

    但是,这里面有一个很重要的问题:二进制读写。这里,我主要讨论二进制操作问题。

     huffman的每一个编码不是等长的,那么,怎么将这些数据对应的编码连接起来,做成完整的数据呢?这里,我想到一个比较不错的想法,跟大家分享下。

    1、在编码的时候,用每一个字符对应的huffman编码,不要用二进制表示,而是字符串表示。比如,假设‘a’对应的编码是‘010’,用的是3个字节+一个‘\0';而非3bit。

    2、在对原始数据编码的时候,很容易的,直接就是字符串的拼接;

    3、对应的编码之后,要将01字符串转成二进制,可以8字节为单位,进制转码;要对一个字节的某个bit位置1还是很容易的(0的话不用操作)。(我这里的话,用的是1024个01字符串作为1组,那么正好转为128个字节的bit;而这个,正好是fd_set这个类型的长度;那么,对bit位的操作,可以调用FD_XXX宏了,比如清零是FD_ZERO,置一是FD_SET;某bit位是否是1可以用FD_TEST)

    4、这样,最终需要长度控制的地方,就是最后的一部分。(所以,在huffman编码的文件,可能还需要记录下最后字节的bit长度)

    当然,在解压缩的时候,需要huffman树,那么在压缩的时候需要保存(我这里想到的是保存对字符数量的统计,然后解压的时候重新建立huffman树)。那么,从bit到字符,也是需要访问huffman树,这里就需要知道对应的bit位是0还是1,这个也很方便(比如我刚刚说的,FD_TEST就可以做到)。

    至此,huffman应该就没多大的问题了。

附:关于huffman编码、压缩,可能只适用于文字压缩;或者,和其他的类型的压缩算法配合。

         另外,还有一个小问题:这类压缩文件,一般都会需要将某些长度保存到压缩文件中去,比如文件长度。这类多字节的整形(比如int),最好的话,还是转为网络字节序保存,这是为了卡平台(可能我想多了 吧^_^)

        最后,关于bit位置值,这里给个另外一种,不借助fd的(可能有的编译环境上没有网络库)。

                   背景条件:对文件的huffman编码之后的'0','1'字符串(以8字节为单位长度);将这类字符串转化为对应的bit。注意:这里没有“善后”:即在最后的时候,可能‘0’,‘1’字符串不满8字节。

char nbit[8]={0x01,  //第一个bit位为1;
              0x02,  //第二个bit位为1;
              0x04,  //第三个bit位为1;
              0x08,
              0x10,
              0x20,
              0x40,  //第七个bit位为1;
              0x80}  //第八个bit位为1;

void setNbit(char *bitBuf,char *data,size_t len)
{
    size_t bitPos = 0;
    for (size_t i=0; i!=len; ++i)
    {
        bitPos = i % 8;
        char &c = *bitBuf;
        c = c | nbit[bitPos];
        if (bitPos == 7)
        {
            ++bitBuf;
        }
    }
}

 附注:由于huffman编码可能会出现极度不平衡的情况,比如:跟节点+左子树+右子树(叶子节点),如此反复;那么,不平衡程度极高,会导致某些节点的编码是很长的,而你的一个节点的编码长度是有限制的,那么这就是个问题。

     这个问题我碰到过,当初是对图像进行编码、压缩。原始数据是像素的,一个字节可以表示;但是huffman编码之后,许多是超过16bit的。

    如果,你想对编码长度进行限制,也许有一种方案可行:平衡二叉树的思想,进行左转、右转。

    我没试过;但是,有空的时候,打算去试试。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值