数据压缩原理与应用 Huffman编码

本文介绍了Huffman编码的基本原理,它是无失真编码的一种,利用概率统计模型进行编码,使得高概率符号编码短,低概率符号编码长,达到数据压缩目的。文章详细阐述了实验流程,包括读取文件、统计频率、建立Huffman树、生成码字和输出文件,并展示了实验结果,指出Huffman编码对符号分布不均的文件压缩效果更佳。

一.Huffman编码的原理

Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman 编码是可变字长编码(VLC)的一种。
Huffman 编码基于信源的概率统计模型,它的基本思路是出现概率大的信源符号编长码,出现概率小的信源符号编短码,从而使平均码长最小。
在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。
在程序实现中常使用一种叫做树的数据结构实现 Huffman 编码,由它编出的码是即时码。

huffman编码流程
统计符号的发生概率
将频率从小到大排序
每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点,这两个叶子节点不再参与比较,新的根节点参与比较
重复第三步
将形成的二叉树的左节点标 0,右节点标 1,把从最上面的根节点到最下面的叶子节点途中遇到的 0,1 序列串起来,就得到了各个符号的编码

举例:
这里写图片描述

  • huffman节点
     /*huffman二叉树*/
    typedef struct huffman_node_tag
    {
        unsigned char isLeaf;//判断是否为叶节点
        unsigned long count;//字符数,字母出现的频率,节点代表的符号加权和
        struct huffman_node_tag *parent;//当前节点的父节点
        union
        {
            struct
            {
                struct huffman_node_tag *zero, *one;//若是叶子,则该项表示信源符号,若不是叶子,则此项为该结点左右孩子的指针
            };
            unsigned char symbol;
        };
    } huffman_node;
  • huffman编码
    typedef struct huffman_code_tag
    {
        /* The length of this code in bits. */
        /*码字的长度(单位:位)*/
        unsigned long numbits;

        /* The bits that make up this code. The first
           bit is at position 0 in bits[0]. The second
           bit is at position 1 in bits[0]. The eighth
           bit is at position 7 in bits[0]. The ninth
           bit is at position 0 in bits[1]. */
           /* 码字, 码字的第 1 位存于 bits[0]的第 1 位,
           码字的第 2 位存于 bits[0]的第的第 2 位,
           码字的第 8 位存于 bits[0]的第的第 8 位,
           码字的第 9 位存于 bits[1]的第的第 1 位 */
        unsigned char *bits;
    } huffman_code;
  • huffman表格
     /*对输出的表格进行结构化 针对huff_run main函数 */
    //输出的表格有些变量可以直接写进结构体里,如此表格可以很快输出,再加入新变量也不会很复杂
    typedef struct huffman_statistics_result
    {
        float freq[256];
        unsigned long numbits[256];
        unsigned char bits[256][100];
    }huffman_stat;

二.实验流程

这里写图片描述


三.代码分析

1.读取待编码的文件

首先对命令行的参数进行定义

    static void
    usage(FILE* out)//命令行参数的设置
    {
        fputs("Usage: huffcode [-i<input file>] [-o<output file>] [-d|-c]\n"
              "-i - input file (default is standard input)\n"//输入文件
              "-o - output file (default is standard output)\n"//输出文件
              "-d - decompress\n"//解压缩操作
              "-c - compress (default)\n"//压缩操作
              "-m - read file into memory, compress, then write to file (not default)\n",//读内存
              "-t - output huffman statistics\n",//输出huffman统计表格
              out);
    }

主函数,对命令行参数进行设计

    int
    main(int argc, char** argv)//命令行参数
    {
        char memory = 0;//内存操作的标识符
        char compress = 1;//解压缩的标识符
        int opt;//命令行参数选项
        const char *file_in = NULL, *file_out = NULL;
        const char *file_out_table = NULL;
        FILE *in = stdin;
        FILE *out = stdout;
        FILE * outTable = NULL;

            /* Get the command line arguments. */
        while((opt = getopt(argc, argv, "i:o:cdhvmt:")) != -1) //读取命令行参数的选项
        {
            switch(opt)
            {
            case 'i':
                file_in = optarg;//选择i,输入文件
                break;
            case 'o':
                file_out = optarg;//选择o,输出文件
                break;
            case 'c':
                compress = 1;//选择c,压缩
                break;
            case 'd':
                compress = 0;//选择d,解压缩
                break
数据压缩是现代计算最重要的领域和工具之一。从获取数据到CD-ROM,从编码理论到图像处理,现代计算的许多层面都依赖于数据压缩。本书对数据压缩的许多不同类型和方示提供了全面的参考。内容包括详尽而有益的分类、最常用方法的描述、方法使用和获益的比较以及“如何”应用的讨论。全书的介绍沿数据的压缩领域的主干来组织、游程编码、统计方法、基于字典的方法、图像压缩、音频压缩和视频压缩。 数据压缩是现代计算最重要的领域和工具之一。从获取数据到CD-ROM,从编码理论到图像处理,现代计算的许多层面都依赖于数据压缩。本书对数据压缩的许多不同类型和方示提供了全面的参考。内容包括详尽而有益的分类、最常用方法的描述、方法使用和获益的比较以及“如何”应用的讨论。全书的介绍沿数据的压缩领域的主干来组织、游程编码、统计方法、基于字典的方法、图像压缩、音频压缩和视频压缩。该书的主要主题为:视频压缩、小波方法、音频压缩、用于JPEG和JBIG的QM编码器、图像变换、用于压缩简单图像的EIDAC方法、前缀图像压缩、ACB和FHM曲线压缩和边缘破碎法。 本书为所有的计算机科学家、计算机工程师、电气工程师、信号/图像处理工程师,以及其他需要一部压缩方法大全的科学家们,提供了一本十分宝贵的参考和指南。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值