数据结构中的哈夫曼编码可以用来制作一个压缩和解压的小项目。因此,需要先写出哈夫曼的编码,具体步骤如下:
首先要创建一个数组,其大小为256,用于存储字节,再从给定路径中逐个读取字节,统计每个字节出现的次数,跟据出现的次数进行排序,此时可以用一个优先队列PriorityQueue,但是PriorityQueue中比较器的方法需要重写过。代码如下:
public class MyComparator implements Comparator<Node>{
public int compare(Node o1, Node o2) {
return o1.count - o2.count;
}
}
比较的是两者的次数,并传入先序队列的构造方法。根据队列的排序逐个取出,然后根据排序构造哈夫曼树,代码如下:
public Node bulid(PriorityQueue<Node> queue) {
// 当队列中至少有2个结点时
while (queue.size() > 1) {
Node node1 = queue.poll();
Node node2 = queue.poll();
// 创建2个子结点的父结点
Node root = new Node(node1.count + node2.count);
node1.parent = root;
node2.parent = root;
root.left = node1;
root.right = node2;
queue.add(root);
}
Node root = queue.poll();
return root;
}
然后根据构造的树进行遍历,得到相应的哈夫曼编码,并记录下来。代码如下:public void traverse(Node root) {
if (root != null) {
if ((root.left == null) && (root.right == null)) {
// System.out.println(root.b);
data data = new data();
data.b = root.b;
data.s = root.sign;
list.add(data);// 将数组加入队列
}
traverse(root.left);
traverse(root.right);
}
}
然后就可以开始进行压缩的工作,先将刚刚的字符串及对应的01编码逐个对应存入文件中,作为头文件。而后用源文件的路径创建输入流,将源文件逐个按字符串输入,根据字符串得到相应的01字符串,将01字符串存入一个byte数组中,待所有源文件均读取完毕后,将得到的与源文件相对于的01字符串数组每8个一取,得到相对于的byte数组。
/**
* 将8位的字符串转化为一个byte类型的字符串
*
* @param str所需转换的01字符串
* @return转换后的byte的字符串
*/
public byte change(String str) {
// 因为转换成数字,而原先传入的只是其字符,所以要减去0所对于的字符码,从而转换的byte才不会溢出
int s = ((int) str.charAt(0) - 48) * 128 + ((int) str.charAt(1) - 48)
* 64 + ((int) str.charAt(2) - 48) * 32
+ ((int) str.charAt(3) - 48) * 16 + ((int) str.charAt(4) - 48)
* 8 + ((int) str.charAt(5) - 48) * 4
+ ((int) str.charAt(6) - 48) * 2 + ((int) str.charAt(7) - 48);
byte by = (byte) s;
return by;
}
若最后末尾不足8位,需要补0,并且要记录补0的个数。// 文件字符串01个数 = 字符次数 * 编码长度
for (int i = 0; i < list.size(); i++) {
data data = list.get(i);
if (data.b < 0) {
data.b += 256;
}
addnum += (datas[data.b] * data.s.length());
}
addzero = 8 - (addnum % 8);
dos.write(addzero);
然后将转换后的byte数组逐个写入压缩文件中。如此,便基本实现了哈夫曼压缩。需要注意的是,如果字符所对应的哈夫曼编码超过8位,可以不用哈夫曼编码,而直接写入该字节即可。这可以算是对哈夫曼压缩的优化。
解压时只有逐个文件写入的顺序读出并进行还原即可以得到原来的文件。
值得注意的是,若创建的为文件基本输入输出流的话,是不可以直接读入一个int,当读取的数据超过一个byte类型的话,需要把int转换为一个byte数组存入,byte数组的大小为4。具体代码如下:
private byte[] Int2Byte(int num) {
byte[] bs = new byte[4];
bs[0] = (byte)((num >>> 24) & 0xFF);
bs[1] = (byte)((num >>> 16) & 0xFF);
bs[2] = (byte)((num >>> 8) & 0xFF);
bs[3] = (byte)((num >>> 0) & 0xFF);
return bs;
}
同样在解压时需要把byte数组还原为一个int,具体实现如下:private int Byte2Int(byte b[]){
int n1=(int)b[0];
int n2=(int)b[1];
int n3=(int)b[2];
int n4=(int)b[3];
int n=((n1 << 24)& 0xFF)+((n2 << 16)& 0xFF)+((n3 << 8)& 0xFF)+((n4 << 0)& 0xFF);
return n;
}
分享到:
相关推荐
实验内容:写出程序,利用哈弗曼编码实现对文件的压缩,并能解压文件。 实验步骤: 1、压缩 (1) 统计原始文件中各字节出现的概率(次数); (2) 采用哈弗曼算法对各字节进行编码,建立哈弗曼对照表; a) 构造...
哈夫曼压缩与解压算法(可以直接运行),压缩成二进制文件,而且生成了txt文件可以查看哈夫曼编码。C++代码
哈夫曼树的应用,实现对TXT文件的压缩和解压,操作简单,需要文件操作
哈夫曼压缩和解压和解压,数据结构课程设计,c++源码。
通过自定义算法创建哈夫曼树和编码,对文件进行二进制操作实现压缩和解压。
一个简单的基于哈夫曼树的压缩解压文件程序
哈夫曼的压缩与解压,我们老师给的代码。 构造Huffman树步骤: 根据给定的n个权值{w1,w2,……wn},构造n棵只有根结点的二叉树,令起权值为wj 在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,...
专业实践,使用哈夫曼编码进行压缩解压
用哈夫曼实现的无损压缩和解压 压缩包中Compress的是压缩有关的所有代码,Decompress是与解压有关的所有代码,编译时需加上 -std=c++11参数
用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAME IS MY FAVORITE”。 字符 A B C D E F G H I J K L M 频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20 字符 N ...
包含实验报告,题目等等,十分详细,物超所值
使用哈夫曼编码统计字符的频率作为权值来实现压缩技术 ,包括哈夫曼树的创建,构造哈夫曼编码,使用哈夫曼编码压缩文件,和解压文件
通过哈夫曼编码实现文件的压缩与解压.pdf
运用哈夫曼编码压缩解压文件源代码,代码有详细的注释,很好的压缩解压的源代码
C语言实现的huffman压缩解压缩算法
NULL 博文链接:https://1471080924.iteye.com/blog/2154500
功能要求 1. 针对一幅BMP格式的图片文件,统计...2. 利用上述哈夫曼树产生的哈夫曼编码对图片文件进行压缩。 3. 压缩后的文件与原图片文件同名,加上后缀.huf(保留原后缀),如pic.bmp 压缩后pic.bmp.huf 4. 解压缩
利用无失真信源编码方法中的哈夫曼编码进行程序设计实践,实现对文件的压缩与解压操作。
哈夫曼编码器,实现了文件的压缩功能,并可以对压缩的文件解压。
使用哈夫曼编码实现文件压缩与解压,产生随机迷宫,并实现最短通路(程序是在ubuntu18.10下跑的)