我是根据B站尚硅谷韩顺平老师讲解的哈夫曼编码代码改写的
b站数据结构和算法
ps:虽然经常翻车(手动狗头) 但还是讲的不错的
因为老韩的解压二进制数组最后一位有bug 我改了一下,增加了一个约定,在要压缩的字符串对应的byte[]数组转为的二进制数组中首位加入了保存最后一位的长度(1-8) 并且约定解码的时候首位不用动 然后判断如果是最后一位了 不管是正数还是负数都要进行补位和截取 截取的长度取决于传入的最后一位的长度(1-8) 经过我的测试暂时是没有问题的 如果有更好的想法可以交流一下
public class Node implements Comparable<Node>{
Byte data; //存放数据的ASCII 'a' => 97
int weight; //权值 该数据出现的次数
Node left;
Node right;
public Node(Byte data, int weight) {
this.data = data;
this.weight = weight;
}
//前序遍历
public void preorderTraversal(){
System.out.println(this);
if (this.left != null){
this.left.preorderTraversal();
}
if (this.right != null){
this.right.preorderTraversal();
}
}
@Override
public int compareTo(Node o) {
return this.weight - o.weight;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", weight=" + weight +
'}';
}
}
public class HuffmanCode {
//哈夫曼编码表
public static Map<Byte,String> codeTable = new HashMap<Byte,String>();
//将字节数组转为Node结点集合
public static List<Node> getNodes(byte[] bytes){
List<Node> nodes = new ArrayList<>();
//遍历传入的bytes 放入map集合中
Map<Byte,Integer> counts = new HashMap<>();
for (byte b:bytes) {
Integer count = counts.get(b);
if (count == null){
counts.put(b,1);
}else {
counts.put(b,++count);
}
}
//遍历map集合
for (Map.Entry<Byte,Integer> entry: counts.entrySet()){
nodes.add(new Node(entry.getKey(),entry.getValue()));
}
return nodes;
}
//根据Node结点集合 创建Huffman树
public static Node createHuffmanTree(List<Node> nodes){
//当数组只剩一个值时代表构建哈夫曼树完毕
while (nodes.size() > 1) {
//排序(升序)
Collections.sort(nodes);
//取出权值最小的两个结点
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
//构建一个新的二叉树
Node parentNode = new Node(null,leftNode.weight + rightNode.weight);
parentNode.left = leftNode;
parentNode.right = rightNode;
//删除权值最小的两个结点
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parentNode);
}
return nodes.get(0);
}
public static Map<Byte,