赫夫曼编码步骤:
1、分析每个字符出现的次数(包括空格),并以字符出现的次数作为权值,构建一个赫夫曼树
2、规定向左路径为 '0',向右路径为 '1',以此来构成一个前缀编码(赫夫曼编码)
前缀编码就是该编码不是其他任何一个编码的前缀
因为每个字符在赫夫曼树上都是叶子结点,因此以路径为编码不会出现二义性
赫夫曼编码压缩比一般在20%~90%之间
import java.util.*;
import java.io.*;
public class Test {
static int count = 0;
static StringBuilder stringBuilder = new StringBuilder();
//Key中元素为将要压缩的数据中出现过的字节
//Value元素为按照字节出现次数为权值构建的赫夫曼树的路径得到的前缀编码
static Map<Byte, String> huffmanMap = new HashMap<>();
public static void main(String[] args) {
String str1 = "文件路径";
String str2 = "文件路径";
byte[] bytes = fileZip(str1, str2);
}
/**
*
* @param bytes 将数据转换成byte数组的形式传入
* @return List集合中存放出现过的字节及出现的次数
*/
public static List<Node> setNode(byte[] bytes) {
List<Node> list = new ArrayList<>();
Map<Byte, Integer> map = new HashMap<>();
for (byte b : bytes) {
Integer count = map.get(b);
if (count == null) {
map.put(b, 1);
} else {
map.put(b, count + 1);
}
}
for (Map.Entry<Byte, Integer> entry : map.entrySet()) {
list.add(new Node(entry.getKey(), entry.getValue()));
}
return list;
}
/**
*将root结点所在的树的所有叶子结点的赫夫曼编码得到,放入huffmanMap中
* @param root 构建的赫夫曼树的头结点
* @param code 前缀编码,赫夫曼树的左分支为0,右分支为1
* @param stringBuilder 用于将路径拼接成赫夫曼编码(前缀编码)
*/
public static void huffmanCode(Node root, String code, StringBuilder stringBuilder) {
StringBuilder stringBuilder1 = new StringBuilder(stringBuilder);
stringBuilder1.append(code);
if (root != null) {
if (root.data == null) {
huffmanCode(root.left, "0", stringBuilder1);
huffmanCode(root.right, "1", stringBuilder1);
} else {
huffmanMap.put(root.data, stringBuilder1.toString());
}
}
}
//重载huffmanCode方法,将传入