• 任意ASCII码格式信息的huffman tree压缩(编码)和解压(译码)


    任意ASCII码格式信息的huffman tree压缩(编码)和解压(译码)

    作者:牛老师,华清远见嵌入式学院讲师。

    计算机实践中发现,大多数信息的表达都存在着一定的冗余度,有效的降低这种冗余度可以使我们用更小的空间存储更大的数据量,同时在有限的通信带宽的情况下,可以传输更多的信息,等等……。那用什么办法可以降低这种冗余度,这里我们学习其中的一种huffman treee压缩(编码)和解压(译码)方法。

    huffman tree的压缩和解压的过程如下:

    1、描述

    对于任意的ASCII格式的信息aba$a@ba*a$a,先统计它们的出现频率a6,b2,$2,*1,@1,然后分别用不等长的01串来编码它们,如a1,b00,$011,*0100,@0101,最后用01串替换原来的信息,得到100101110101001010010111,并按二进制位组合,这样就可以得到压缩后的文件。

    相对应,解压时必须知道编码a1,b00,$011,*0100,@0101,然后根据100101110101001010010111一步步解压得到aba$a@ba*a$a原始信息。

    2、分析

    为了解压成功,首先必须保证任何已经编码的单个字符不能是其他字符编码的前缀,也就是说用1编码a以后,其他字符编码不能以1开头。为了实现压缩的最小,同时要保证出现频率最高的字符编码最短,频率最低的编码最长。

    3、方法

    通过描述和分析,我们明白这种方法是可以实现压缩文件的,用什么办法可以实现这种方法呢?使用最优二叉树也就是huffman tree可以实现上面的方法,步骤如下:

    1) 将a6,b2,$2,*1,@1按照频率值从小到大有序入队,出队两个元素,分别以它们为左右子树,建立二叉树,并将它们出现次数之和作为根节点,把根节点有序入队。

    @1      *1      $2      b2      a6

        2           $2       b2    a6
          / \
        @1     *1

    2) 然后重复1步骤直到队中只剩下一个节点,该节点就是所求huffman tree的根节点,最后按照左0,右1进行编码a1,b00,$011,*0100,@0101。

    b2      4      a6
              / \
            2      $2
          / \
        @1      *1

        6      a6
          / \
        b2      4
              / \
            2      $2
          / \
        @1      *1

             12
              0/  1\
             6        a6
         0/  1\      1
        b2        4
        00    0/  1\
             2        $2
         0/  1\     011
        *1       @1
        0100     0101

    4、步骤
            第一步:统计aba$a@ba*a$a字符出现的频率,a6,b2,$2,*1,@1。
            第二步:去除重复的字符ab$@*。
            第三步:创建huffman tree,对ab$@*进行编码a1,b00,$011,*0100,@0101。
            第四步:aba$a@ba*a$a根据编码a1,b00,$011,*0100,@0101压缩为10010111010
                            1001010010111。
            第五步:100101110101001010010111根据huffman tree解压为aba$a@ba*a$a。

    5、实现

    treehuffman.c

    1. #include <stdio.h>
            2. #include <stdlib.h>
            3. #include <string.h>
            4. #include "treehuffman.h"
            5. #include "../queue/queuelink.h"
            6.
            7. treehuffman *treecreate(char *s)
            8. {
            9.           int w[256] = {};
            10.         int i;
            11.         char c[256] = {}, *pc = c;
            12.         queuelink *q = queuecreate();
            13.        queuedata temp;
            14.
            15.         // 第一步
            16.         while(*s != '')
            17.         {
            18.                 w[(int)*s++]++;
            19.         }
            20.
            21.         // 第二步
            22.         for(i=0; i<256; i++)
            23.         {
            24.                if(w[i] != 0)
            25.                 {
            26.                         *pc++ = i;
            27.                 }
            28.         }
            29.
            30.         // 第三步
            31.         pc = c;
            32.         while(*pc != '')
            33.         {
            34.                 temp = (treehuffman *)malloc(sizeof(treehuffman));
            35.
            36.                 temp->c = *pc;
            37.                 temp->w = w[(int)*pc++];
            38.                 temp->code[0] = '';
            39.                 temp->lchild = temp->rchild = NULL;
            40.
            41.                 queueenterorder(q, temp);
            42.         }
            43.
            44.         while(q->front->next != q->rear)
            45.         {
            46.                 temp = (treehuffman *)malloc(sizeof(treehuffman));
            47.
            48.                temp->code[0] = '';
            49.                 temp->lchild = queuedelete(q);
            50.                 temp->rchild = queuedelete(q);
            51.                 temp->w = temp->lchild->w+temp->rchild->w;
            52.
            53.                queueenterorder(q, temp);
            54.        }
            55.
            56.         return queuedelete(q);
            57. }
            58.
            59. // 第四步
            60. char *treecompress(treehuffman *t, char *s, char *compressed)
            61. {
            62.         queuelink *q = queuecreate();
            63.         queuedata temp;
            64.         char *code[256];
            65.
            66.         queueenter(q, t);
            67.
            68.         while(queueempty(q) == 0)
            69.        {
            70.                 temp = queuedelete(q);
            71.
            72.                 if(temp->lchild==NULL && temp->rchild==NULL)
            73.                 {
            74.                         code[(int)temp->c] = temp->code;
            75.                         printf("%c(%d) : %s ", temp->c, temp->w, temp->code);
            76.                 }
            77.
            78.                 if(temp->lchild != NULL)
            79.                 {
            80.                         strcpy(temp->lchild->code, temp->code);
            81.                         strcat(temp->lchild->code, "0");
            82.                         queueenter(q, temp->lchild);
            83.                 }
            84.
            85.                 if(temp->rchild != NULL)
            86.                 {
            87.                        strcpy(temp->rchild->code, temp->code);
            88.                        strcat(temp->rchild->code, "1");
            89.                         queueenter(q, temp->rchild);
            90.                 }
            91.         }
            92.
            93.        while(*s != '')
            94.         {
            95.                strcat(compressed, code[(int)*s++]);
            96.         }
            97.
            98.         return compressed;
            99. }
            100.
            101. // 第五步
            102. char *treeuncompress(treehuffman *t, char *compressed, char *compress)
            103. {
            104.        char *p = compress;
            105.        treehuffman *temp = t;
            106.
            107.        while(*compressed != '')
            108.        {
            109.                if(*compressed++ == '0')
            110.                {
            111.                        temp = temp->lchild;
            112.                }
            113.                else
            114.                {
            115.                        temp = temp->rchild;
            116.                }
            117.
            118.                if(temp->lchild==NULL && temp->rchild==NULL)
            119.                {
            120.                        *compress++ = temp->c;
            121.                        temp = t;
            122.                }
            123.        }
            124.
            125.        return p;
            126. }

    1treehuffman.h

    127. #ifndef __TREEHUFFMAN_H__
            128. #define __TREEHUFFMAN_H__
            129.
            130. typedef char treedata;
            131.
            132. typedef struct tree
            133. {
            134.        treedata c;
            135.        int w;
            136.        char code[16];
            137.        struct tree *lchild, *rchild;
            138. }treehuffman;
            139.
            140. extern treehuffman *treecreate(char *s);
            141. extern char *treecompress(treehuffman *t, char *s, char *compressed);
            142. extern char *treeuncompress(treehuffman *t, char *compressed, char *compress);
            143.
            144. #endif

    注意:对于a6,b2,$2,*1,@1来说,结果可能有几种,可能是a1,b00,$011,*0100,@0101,也可以是a1,$00,b011,@0100,*0101。这是因为统计的频率中有相等的,所以在有序入队时他们可能是左子树,也可能是右子树,所以出来的结果可能与程序本身的处理有关,不过不影响最终的压缩率。

  • 相关阅读:
    RDD(弹性分布式数据集)的分析
    Spark 开发环境搭建
    本地yum仓库的配置安装
    Java使用PDFBox操作PDF文件获取页码、文章内容、缩略图
    利用bdb实现持久化队列
    SQL查询重复记录
    SQL删除某个时间段的数据
    JAVA文件读取和解析
    多线程
    DOC解析xml
  • 原文地址:https://www.cnblogs.com/shulianghe/p/3724134.html
Copyright © 2020-2023  润新知