赫夫曼算法类 Huffman.java
/**
- @Author: ltx
- @Description: 赫夫曼编码
*/
public class Huffman {
Map<Character, String> codeMap = new HashMap<>();/** * 中序遍历(前序或后序也行) * 失去huffman编码 * * @param node 节点 * @param sb StringBuilder */public void getCodeByMidOrder(Node node, StringBuilder sb) { if (node.left != null) { //往左走+'0' sb.append("0"); getCodeByMidOrder(node.left, sb); } //叶子节点 if (node.left == null && node.right == null) {
// System.out.print(node + ":" + sb + ", ");
codeMap.put(node.value, sb.toString()); } if (node.right != null) { //往右走+'1' sb.append("1"); getCodeByMidOrder(node.right, sb); } //回溯向上走缩小一个字符 if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); }}public Node getHuffmanTree(List<Node> nodes) { Collections.sort(nodes);
// System.out.println(nodes);
while (nodes.size() > 1) { //左叶子-数组最小值 Node leafLeft = nodes.remove(0); //右叶子-数组次小值 Node leafRight = nodes.remove(0); //父节点=数组最小值+数组次小值 Node parentNode = new Node(null, leafLeft.weight + leafRight.weight); parentNode.left = leafLeft; parentNode.right = leafRight; //新的节点增加到list外面 nodes.add(parentNode); Collections.sort(nodes); } return nodes.get(0);} /** * 获取各个字符权重(字符个数) * * @param str * @return */public List<Node> getCharWight(String str) { Map<Character, Integer> charNumMap = new HashMap<>(); char[] chs = str.toCharArray(); for (char c : chs) { //数量 Integer count = charNumMap.get(c); if (count == null) { charNumMap.put(c, 1); } else { charNumMap.put(c, count + 1); } }
// System.out.println(charNumMap);
List<Node> nodes = new ArrayList<>(); //创立节点List for (char c : charNumMap.keySet()) { nodes.add(new Node(c, charNumMap.get(c))); } return nodes;} /** * 编码 * 依据赫夫曼编码表,对原始数据做转换 * * @param str 原始字符串 * @return */public String encoding(String str) { StringBuilder sb = new StringBuilder(); char[] chs = str.toCharArray(); for (char c : chs) { sb.append(codeMap.get(c)); } return sb.toString();} /** * 解码 * * @return */public String decode(String encodStr) { //翻转codeMap Map<String, Character> encodeMap = new HashMap<>(); for (char c : codeMap.keySet()) { encodeMap.put(codeMap.get(c), c); } char[] chs = encodStr.toCharArray(); int j = 0; StringBuilder res = new StringBuilder(); while (j < encodStr.length() - 1) { StringBuilder sb = new StringBuilder(); Character cr; //匹配出字符串 while ((cr = encodeMap.get(sb.toString())) == null) { sb.append(chs[j]); j++; } res.append(cr); } return res.toString();}public static void main(String[] args) { Huffman huffman = new Huffman(); System.out.println("原始数据:"); //须要压缩的串 String str = "i like like like java do you like a java"; System.out.println(str); //1.取得字符权重List List<Node> nodes = huffman.getCharWight(str); //[ :9, a:5, d:1, e:4, u:1, v:2, i:5, y:1, j:2, k:4, l:4, o:2] System.out.println("节点权重列表:"); System.out.println(nodes); //2.[PerfectMoney下载](https://www.gendan5.com/wallet/PerfectMoney.html)结构赫夫曼树 Node root = huffman.getHuffmanTree(nodes); //3.取得赫夫曼编码表 huffman.getCodeByMidOrder(root, new StringBuilder("")); System.out.println("赫夫曼编码表:"); //失去赫夫曼编码表 //{ =01, a=100, d=11000, u=11001, e=1110, v=11011, i=101, y=11010, j=0010, k=1111, l=000, o=0011} System.out.println(huffman.codeMap); //4.压缩编码 String encodStr = huffman.encoding(str); System.out.println("压缩后数据:");
//1010100010111111110010001011111111001000101111111100100101001101110001110000011011101000111100101000101111111100110001001010011011100
System.out.println(encodStr); //5.解压 String res = huffman.decode(encodStr); System.out.println("解压后数据:"); //打印最终后果 //i like like like java do you like a java System.out.println(res);}
}