三、哈夫曼编码生成步骤:
① 扫描要压缩的文件,对字符出现的频率进行计算。
② 把字符按出现的频率进行排序,组成一个队列。
③ 把出现频率最低(权值)的两个字符作为叶子节点,它们的权值之和为根节点组成一棵树。
④ 把上面叶子节点的两个字符从队列中移除,并把它们组成的根节点加入到队列。
⑤ 把队列重新进行排序。重复步骤 ③④⑤ 直到队列中只有一个节点为止。
⑥ 把这棵树上的根节点定义为 0 (可自行定义 0 或 1 )左边为 0 ,右边为 1 。这样就可以得到每个叶子节点的哈夫曼编码了。
既如 (a) 、 (b) 、 (c) 、 (d) 几个图,就可以将离散型的数据转化为树型的了。
如果假设树的左边用0 表示右边用 1 表示,则每一个数可以用一个 01 串表示出来。
则可以得到对应的编码如下:
1-->110
2-->111
3-->10
4-->0
每一个01 串,既为每一个数字的哈弗曼编码。
为什么能压缩:
压缩的时候当我们遇到了文本中的1 、 2 、 3 、 4 几个字符的时候,我们不用原来的存储,而是转化为用它们的 01 串来存储不久是能减小了空间占用了吗。(什么 01 串不是比原来的字符还多了吗?怎么减少?)大家应该知道的,计算机中我们存储一个 int 型数据的时候一般式占用了 2^32-1 个 01 位,因为计算机中所有的数据都是最后转化为二进制位去存储的。所以,想想我们的编码不就是只含有 0 和 1 嘛,因此我们就直接将编码按照计算机的存储规则用位的方法写入进去就能实现压缩了。
比如:
1这个数字,用整数写进计算机硬盘去存储,占用了 2^32-1 个二进制位
而如果用它的哈弗曼编码去存储,只有110 三个二进制位。
效果显而易见。
开始写程序:
开始些程序之前,必须想好自己的文件存储格式,和存储规则是什么
为了简便,我自定义存储的基本信息,格式如下:
SaveCode[i].n int型 // 每一个字节的编码长度 i:0~256
B yte[] byte数组型 // 每一个字节的编码 SaveCode[i].node 中 String 的 01 串转化而来。
Byte[] byte数组型 // 对文件中每一个 byte 的重新编码的哈夫曼编码写入。
有了定义好的格式我们的读写就非常的方便了,
创建步骤:
①读入文件中的所有字节:
Java代码// 创建文件输入流
java.io.FileInputStream fis = newjava.io.FileInputStream(path);
//读入所有的文件字节
while(fis.available()>0){
inti=fis.read();
byteCount[i]++;
}
②构建哈夫曼树:
Java代码/**
* 使用优先队列构建哈弗曼树
*/
publicvoidcreateTree(){
//