数据压缩实验三——霍夫曼编解码算法实现

本文介绍了霍夫曼编码的原理和实现过程,包括统计字符频率、构建霍夫曼树、编码与解码流程。通过实验展示了不同文件的压缩效率,证明了霍夫曼编码在概率分布不均匀的信源中能有效提高压缩比。
摘要由CSDN通过智能技术生成

一、实验原理

霍夫曼编码

  1. Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman编码是可变字长编码(VLC)的一种。
  2. Huffman 编码基于信源的概率统计模型,它的基本思路是,出现概率大的信源符号编长码,出现概率小的信源符号编短码,从而使平均码长最小。
  3. 在程序实现中常使用一种叫做树的数据结构实现Huffman编码,由它编出的码是即时码

霍夫曼编码方法

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

二、实验流程及代码分析

实验流程

  1. 读入待编码的源文件
  2. 第一次扫描:统计文件中各个字符出现频率
  3. 建立Huffman树
  4. 将码表及其他必要信息写入输出文件
  5. 第二次扫描:对源文件进行编码并输出

霍夫曼编码的数据结构

霍夫曼节点结构:

typedef struct huffman_node_tag
{
    unsigned char isLeaf;               //是否为树叶
    unsigned long count;                //节点代表的符号加权和
    struct huffman_node_tag *parent;  //父节点指针
    union
    {
        struct
        {
                struct huffman_node_tag *zero, *one;   
                //子节点指针,分别代表0,1子节点指针
        };
    unsigned char symbol;             //节点代表的符号
    }; 
} huffman_node; 

霍夫曼码结构:

typedef struct huffman_code_tag
{
    unsigned long numbits;            //该码所用的比特数
unsigned char *bits;            //指向该码比特串的指针
    // 76543210 | bit[0]
    // ******98 | bit[1]
} huffman_code; 

霍夫曼统计结构

typedef struct huffman_statistics_result
{
    // 霍夫曼码字统计结果结构体,包含每个树叶节点的频率、位数、码字
    float freq[256];
    unsigned long numbits[256];
    // 以字节为单位存放码字
    unsigned char bits[256][100];
}huffman_stat;

代码分析

编码流程
主程序

读入待编码源文件及调用霍夫曼编码函数。

int main(int argc, char** argv)
{
    char memory = 0;
    // 是否读取内存数据操作,0为否
    char compress = 1;
    // 压缩或解压缩,1为压缩
    // ......省略文件初始化
    //step1:add by yzhang for huffman statistics
    FILE * outTable = NULL;
    // 输出的码字统计结果excel表格文件
    //end by yzhang

    /* Get the command line arguments. */
    while((opt = getopt(argc, argv, "i:o:cdhvmt:")) != -1) 
    {
        // 使用getopt函数读取命令行参数
        switch(opt)
        {
        case 'i':
            file_in = optarg;
            break;
        case 'o':
            file_out = optarg;
            break;
        ......
        }
    }

    /* If an input file is given then open it. */
    ......
    /* If an output file is given then create it. */
    ......
    /* If an out table file is given then create it. */
    ......

    if(memory)
    {
        // 是否读取内存数据进行压缩或解压操作
        return compress ?
            memory_encode_file(in, out) : memory_decode_file(in, out);
    }

    if(compress)  //change by yzhang
        // 是否对读入文件进行压缩或解压缩操作
        huffman_encode_file(in, out,outTable);
        //step1:changed by yzhang from huffman_encode_file(in, out) to huffman_encode_file(in, out,outTable)
    else
    huffman_decode_file(in, out);

    //......省略关闭文件操作

    return 0;
}

函数嵌套结构与功能
– huffman_encode_file 读文件,输出码表、编码后文件
– get_symbol_frequencies 构造叶子节点
– init_frequencies 初始化叶子节点
– new_leaf_node 建构造叶子节点
– huffST_getSymFrequencies 保存码字频率统计结果
– calculate_huffman_codes 组织霍夫曼二叉树结构
– qsort / SFComp 排序/规则为从小到大
– new_nonleaf_node 构造非叶子节点
– build_symbol_encoder 生成码字
– huffST_getcodeword 保存码字
– output_huffman_statistics 输出码字统计结果
– fprintf 写文件
– write_code_table 码表写入文件
– do_file_encode 读文件,查表编码,写入文件

霍夫曼编码函数

主函数

int 
huffman_encode_file(FILE *in, FILE *out, FILE *out_Table)  
//step1:changed by yzhang for huffman statistics from (FILE *in, FILE *out) to (FILE *in, FILE *out, FILE *out_Table)
{
    SymbolFrequencies sf;
    // 叶子结点结构体数组
    SymbolEncoder *se;
    // 码节点结构体数组
    huffman_node *root = NULL;
    // 根节点,初始化为空
    int rc;
    unsigned int symbol_count;
    // 总符号数
    //step2:add by yzhang for huffman statistics
    huffman_stat hs;
    // 霍夫曼统计结构体
    //end by yzhang

    /* Get the frequency of each symbol in the input file. */
    symbol_count = get_symbol_frequencies(&sf, in); 
    // 为出现过的符号建立叶子节点,并返回总符号数

    //step3:add by yzhang for huffman statistics,...  get the frequency of each symbol 
    huffST_getSymFrequencies(&sf,&hs,symbol_count);
    // 保存各码字频率统计结果,给霍夫曼统计结构体
    //end by yzhang

    /* Build an optimal table from the symbolCount. */
    se = calculate_huffman_codes(&sf);
    // 构造非叶子节点、组织霍夫曼二叉树结构、生成霍夫曼码字,返回霍夫曼码字结构体
    root = sf[0];
    // 保存根节点

    //step3:add by yzhang for huffman statistics... output the statistics to file
    huffST_getcodeword(se, &hs);
    // 保存码字
    output_huffman_statistics(&hs,out_Table);
    // 输出统计结果
    //end by yzhang

    /* Scan the file again and, using the table
       previously built, encode it into the output file. */
    rewind(in);
    // 文件指针重新指向首地址
    rc = write_code_table(out, se, symbol_count);
    // 将码表写入文件
    if
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值