思路:
- 将赫夫曼编码表存放在Map<Byte,String> 形式:32->01,97->100,100->11000等等。[形式]
- 在生成赫夫曼编码表时,需要去拼接路径,定义一个StringBuilder 存储某个叶子结点的路径。
流程图如下:
分布代码1——生成哈夫曼树对应的哈夫曼编码:
测试:
分布代码2——字节数组根据编码表生成编码数据:
编写一个方法,将一个字符串对应的byte[],通过生成的赫夫曼编码表,返回一个赫夫曼编码 压缩后的byte[].
测试:
将原来 "i like like like java do you like a java"这40个字节的数据,压缩成了17个字节的数据。
完整代码:
1、封装前的分步代码:
package com.huey.huffmancode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HuffmanCode {
public static void main(String[] args) {
// TODO Auto-generated method stub
String content = "i like like like java do you like a java";
byte[] contentBytes = content.getBytes();
System.out.println(contentBytes.length);// 40
List<Node> nodes = getNodes(contentBytes);
System.out.println("nodes=" + nodes);
// 测试创建的赫夫曼树
System.out.println("赫夫曼树");
Node huffmanTreeRoot = createHuffmanTree(nodes);
System.out.println("前序遍历");
huffmanTreeRoot.preOrder();
// 测试是否生成了对应的哈夫曼编码
Map<Byte, String> huffmanCodes = getCodes(huffmanTreeRoot);
System.out.println("生成的哈夫曼编码表:" + huffmanCodes);
// 测试
byte[] huffmanCodeBytes = zip(contentBytes, huffmanCodes);
System.out.println("huffmanCodeBytes=" + Arrays.toString(huffmanCodeBytes));// 17
//(40-17) / 40 = 0.575
//发送huffmanCodeBytes 数组
}
// 编写一个方法,将一个字符串对应的byte[],通过生成的赫夫曼编码表,返回一个赫夫曼编码 压缩后的byte[]
/**
* @param bytes 这是原始的字符串对应的byte[]
* @param huffmanCodes 生成的赫夫曼编码
* @return 举例:String content ="i like like like java do you like a java"; =>
* byte[] contentBytes = content.getBytes();
* 注:存储在计算机里的都是补码,一个byte是8位,开头一个是符号位 返回的是:
* 字符串:"101010001011111111001000101111111100100010111111110010010100110111000
* 1110000011011101000111100101000101111111100110001001010011011100"
* 长度是133,正是上面content中字符串(含空格)的哈夫曼编码拼接后的字符长度。
* 对应的byte[] huffmanCodeBytes
* 即8位对应一个byte,放入到huffmanCodeBytes huffmanCodeBytes[0] = 10101000(补码) =>
* [推导 10101000=>10101000-1=>10100111(反码)=>11011000 = -88(前面符号位为负)]
*/
private static byte[] zip(byte[