`
李瑞辉++
  • 浏览: 20810 次
  • 性别: Icon_minigender_1
  • 来自: 信阳
社区版块
存档分类
最新评论

哈弗曼树以及压缩运用

 
阅读更多



     
一.介绍

其实在还没有学习压缩之前,在学校学习中已经接触到了哈弗曼,而且已经了解哈弗曼是如何进行编码和解码,只是没有通过编程实现而已,现在就大致介绍一下哈弗曼树。

设根树Tt片树叶V1V2......Vi,给每一片树叶赋一个权值W1,W2......Wi,则称为T赋权二叉树,其中L(Vi)为叶子节点Vi到根节点的长度,如果存在一种赋权方式,使得 ,则称这棵树为最优二叉树,即哈弗曼树。

WPL的计算方法

由以上的计算方式可以的出,哈弗曼树的WPL是最小的。完全二叉树不一定是哈弗曼树。

二.构造方法及编码

HuffMan树的构造方法:

1)对所有权值从低到高排队。

2)找出两个最小的权值,记为W1W2

3)用(W1W2)代替W1W2,产生新的队列。

4)若队列中的点数大于1,则回到第一步,否则进行下一步。

5)逆序将以上组合过程画出来得到HuffMan树。

构造原则:左小右大、组合优先、左01、不足补零

 

哈弗曼树构造图:



 

按照上面介绍的原则:可得出每一个字符对应的编码

a 0;   b : 10;  c : 110; d : 111

 

三.哈弗曼压缩以及实现原理

对于现代科技的高速发展,数据的存储和传输越来越多,量也越来越大,对于存储和传输的介质要求越来越高,所以如果能进行数据压缩,将在一定程度上解决这个问题。哈弗曼压缩是一种无损压缩,对于大部分文件数据是不允许有任何损失的,所以哈弗曼对于此类文件的压缩无疑是非常好的选择。

四.哈弗曼压缩的实现

哈弗曼压缩就是通过用01串构成的编码代替字符的存储,就像上面的的a,b,c,d四个字符,一个字符在文件存储时需要两个字节及16位,四个就需要64位,而用上面的编码把他们变成01串即为010110111 之后,可以看出占用的空间明显小了很多。

1).权值的获取:其实此时的权值即为-128~127中每个字节在文件里出现的次数,然后按照上面的构造方法构造哈夫曼树,可以看出,重复率越高的字节最终的编码越短,这样就达到压缩的目的了

 

//计算文件中每个字节出现的次数

           while (bis2.available() > 0) {

              int i = bis2.read();

              date[i]++;

      }

 

2).构建哈夫曼树

先以每个出现的字节以及出现的次数创建结点对象,把他们放入事先定义好的优先队列(hufQueue)中去

// 构建哈夫曼树

       while (hufQueue.size() > 1) {

           

           hufNode min1 = hufQueue.poll();// 获取头对象,获得并删除对象

           hufNode min2 = hufQueue.poll();

           

           //通过两个子节点合成一个父节点

           hufNode result = new hufNode(0, min1.getTimes() + min2.getTimes());

           

           //设定左右子节点

           result.setLeftChild(min1);

           result.setRightChild(min2);

           

         hufQueue.add(result);// 加入合并节点

}

 

3).获得编码,其中以根节点为起始点进行编码,并存入数组中

/**

     * 获得编码

     * @param root  : 根节点

     * @param s     :编码

     */

    public void getCode(hufNode root, String s) {

 

       if ((root.getLeftChild() == null) && (root.getRightChild() == null)) {// 左右子节点都为空,则编码结束

           //创建一个编码对象

           Code code = new Code(s.length(),s);

       

           saveCode[root.getDate()] = code;

       }

 

       if (root.getLeftChild() != null) {// 左子节点不为null,则继续编码

           getCode(root.getLeftChild(), s + "0");// 左 0

       }

 

       if (root.getRightChild() != null) {// 右子节点不为null,则继续编码

           getCode(root.getRightChild(), s + "1");// 右 1

       }

}

 

 

4).写入码表,因为有解压肯定要解压,如果直接给你一长串01串,谁也不知到是什么意思,所以必须把压缩方式写进去,以方便解压缩,写入码表的方式是把所有的字节编码连起来,然后8个一截取,转化为字节然后再存储到文件里,

当最后不足8个时就用0补齐再存储,需要注意的是在写入码表之前要把每一个字节对应编码的长度先写入文件,以方便解压时的截取

while ((bis.available() > 0) || (count >= 8)) {

              // 如果缓冲区的写入字符个数大于8

              if (count >= 8) {

                  // 清空要转化的字符串

                  waiteString = writes.substring(0, 8);

                  

                  // 去除writes的前8位

                  writes = writes.substring(8);

                  

                  count -= 8;// 写入一个8位字节

                  int tempw = changeString(waiteString);

                  // 写入文件

                  bos2.write(tempw);

 

              } else {

                  

                  idate = bis.read();

                  // 得到第i个字节的编码信息

                  count += saveCode[idate].getN();

                  writes += saveCode[idate].getNode();

                  

              }

           }

 

 

 

5).解析文件,完成压缩,其实这一步就是把文件里字节一个一个读取出来然后与码表进行比对,换成对应的编码,然后再重新写入文件,方式与写入码表时是一样的。这是压缩的整个过程,对于小文件,由于码表的写入,也许最终压缩后的占用空间并不一定减小,但对于较大的文件和重复率较高的文件最终的压缩率还是比较可观的。

  • 大小: 8.8 KB
  • 大小: 9.3 KB
2
14
分享到:
评论

相关推荐

    指针实现哈弗曼树

    总的来说,哈弗曼树的实现涉及到指针操作、数据结构设计、以及优化算法的运用。通过这个简单的模块化编程实践,我们可以深入理解二叉树、优先队列和编码技术在数据压缩中的应用。同时,这也为我们提供了一个提升编程...

    数据结构作业之二哈弗曼树

    对于学习数据结构的同学来说,理解和掌握哈弗曼树的构建过程、编码方法以及其在实际问题中的应用是非常重要的。通过动手实践,例如编写哈弗曼树的构造和编码解码程序,可以加深对这一概念的理解。在完成“数据结构...

    哈弗曼树编码译码系统

    通过频率统计、构建哈弗曼树、生成编码以及保存和应用编码表,可以实现高效的数据压缩和恢复。在数据结构课程设计中,这样的项目可以帮助学生深入理解和应用数据结构与算法,提升编程实践技能。

    哈弗曼编码器 并以直观方式显示哈弗曼树

    - `HTNode`用于表示哈弗曼树的节点,包含了字符、标记、权重以及指向父节点和子节点的指针。 - `HuffmanTree`是指向`HTNode`类型的指针,通常用于表示哈弗曼树的根节点。 - `Select`函数用于选择权值最小的两个节点...

    用数据结构编写哈弗曼树

    哈弗曼树(Huffman Tree),也称为最优二叉树,是数据结构中的一种特殊树形结构,主要用于数据编码和解码,特别是在数据压缩领域有着广泛的应用。它是由美国计算机科学家大卫·艾伦·哈弗曼在1952年提出的一种自底...

    基于哈弗曼编码的数据压缩解压程序论文

    论文中展示了压缩和解压过程的具体步骤,包括输入文件的预处理、压缩过程中的编码生成、压缩文件的存储格式,以及解压过程中哈弗曼树的重建和解码过程。 通过这篇论文,学生不仅能够学习到哈弗曼编码的理论知识,还...

    数据结构课程设计基于MFC的哈弗曼树

    在计算机科学领域,数据结构是构建高效算法的基础,而哈弗曼树(Huffman Tree)作为一种特殊的二叉树,因其在数据编码与压缩中的优异性能,被广泛应用于信息传输和存储。MFC(Microsoft Foundation Classes)是微软...

    数据结构 用C++环境编写程序 构建哈弗曼树

    在IT领域,数据结构是计算机...总的来说,通过这次实验,你将学习到如何在C++环境中运用数据结构和算法,具体来说是哈弗曼树和贪心策略,解决实际问题,这对于理解和提升编程能力以及后续的软件开发都是非常有益的。

    哈弗曼,树,编码

    - `HuffmanCoding`函数实现哈弗曼树的构建及编码生成过程,包括初始化节点、选择并合并节点、以及编码生成等关键步骤。 #### 示例分析 在`HuffmanCoding`函数中,首先根据输入的字符频率数组`w`和字符数量`n`,动态...

    c++数据结构 哈弗曼

    哈弗曼树的构建过程旨在最小化带权路径长度(WPL),从而实现高效的数据压缩。 1. **哈弗曼树的概念** 哈弗曼树是一种带权路径长度最短的二叉树,也称为最优二叉树。在哈弗曼树中,频率较高的字符对应的路径较短,...

    C++ 哈弗曼树

    哈弗曼树,又称最优二叉树或...理解并能熟练运用哈弗曼树,对提升算法能力、优化问题解决具有重要意义。在C++中实现哈弗曼树,需要掌握数据结构、算法以及标准库的使用,这对于提升编程技能和解决问题的能力至关重要。

    哈弗曼压缩软件(数据结构试验报告附源程序).pdf

    设计技巧包括了对字母和汉字的共同压缩,以及压缩后的哈弗曼树存储方式,仅保存叶子节点的字符、左右孩子信息,非叶子节点仅保存左右孩子。解压时,从根节点开始,根据0和1的指引找到对应的叶子节点输出字符。 从这...

    huffman树(数据结构)

    哈弗曼树,又称最优二叉树或...理解哈弗曼树的概念和构建方法,以及如何运用它进行数据压缩,对于学习数据结构和算法以及解决实际问题至关重要。通过阅读16huffman中的文件,可以更深入地掌握哈弗曼树的实践应用。

    哈弗曼编码进行数字编码

    在构建哈弗曼树的过程中,首先统计每个字符出现的频率,然后创建一个由频率决定权重的二叉树。初始时,每个字符都是一个叶子节点,形成单个节点的树。接着,每次将两个权重最小的树合并成一个新的树,新树的权重是两...

    文件压缩与解压实验报告.docx

    4. 主函数和其他辅助函数,如哈弗曼树类的成员函数,用于绘制哈弗曼树和输出节点信息。 实验过程中,使用了C++编程语言,通过创建和操作自定义的哈弗曼结点结构体来构建和操作哈弗曼树。在哈弗曼编码过程中,通过对...

    数据结构哈弗曼编译\码课程设计

    其基本思想是创建一棵特殊的二叉树,即哈弗曼树,树中的每个叶子节点代表一个字符,而从根节点到每个叶子节点的路径表示该字符的编码。频率较高的字符对应的编码通常较短,从而实现高效的数据压缩。在编码过程中,...

    数据结构上机作业之哈弗曼编码

    哈弗曼编码的基本思想是构建一棵特殊的二叉树——哈弗曼树(也称为最优二叉树)。这棵树的每个叶子节点代表一个需要编码的字符,而内部节点则不携带任何字符信息。哈弗曼树的特点是:频率较高的字符对应的路径较短,...

Global site tag (gtag.js) - Google Analytics