创建赫夫曼树、生成赫夫曼编码、数据的压缩可见9.3节:
点击链接
直接看//测试第六步:完成数据的解压
package com.atguigu.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;
import java.util.Map.Entry;
public class HuffmanCode {
public static void main(String[] args) {
String content = "i like like like java do you like a java";
byte[] contentBytes = content.getBytes();
System.out.println(contentBytes.length);
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));
byte[] huffmanCodesBytes = huffmanZip(contentBytes);
System.out.println("huffmanCodeBytes="+ Arrays.toString(huffmanCodeBytes));
byte[] sourceBytes = decode(huffmanCodes, huffmanCodesBytes);
System.out.println("原来的字符串=" + new String(sourceBytes));
}
private static byte[] decode(Map<Byte,String> huffmanCodes, byte[] huffmanBytes) {
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < huffmanBytes.length; i++) {
byte b = huffmanBytes[i];
boolean flag = (i == huffmanBytes.length - 1);
stringBuilder.append(byteToBitString(!flag, b));
}
Map<String, Byte> map = new HashMap<String,Byte>();
for(Map.Entry<Byte, String> entry: huffmanCodes.entrySet()) {
map.put(entry.getValue(), entry.getKey());
}
List<Byte> list = new ArrayList<>();
for(int i = 0; i < stringBuilder.length(); ) {
int count = 1;
boolean flag = true;
Byte b = null;
while(flag) {
String key = stringBuilder.substring(i, i+count);
b = map.get(key);
if(b == null) {
count++;
}else {
flag = false;
}
}
list.add(b);
i += count;
}
byte b[] = new byte[list.size()];
for(int i = 0;i < b.length; i++) {
b[i] = list.get(i);
}
return b;
}
private static String byteToBitString(boolean flag, byte b) {
int temp = b;
if(flag) {
temp |= 256;
}
String str = Integer.toBinaryString(temp);
if(flag) {
return str.substring(str.length() - 8);
} else {
return str;
}
}
private static byte[] huffmanZip(byte[] bytes) {
List<Node> nodes = getNodes(bytes);
Node huffmanTreeRoot = createHuffmanTree(nodes);
Map<Byte, String> huffmanCodes = getCodes(huffmanTreeRoot);
byte[] huffmanCodeBytes = zip(bytes, huffmanCodes);
return huffmanCodeBytes;
}
private static byte[] zip(byte[] bytes, Map<Byte, String> huffmanCodes){
StringBuilder stringBuilder = new StringBuilder();
for(byte b : bytes){
stringBuilder.append(huffmanCodes.get(b));
}
int len;
if(stringBuilder.length() % 8 == 0){
len = stringBuilder.length() / 8;
}else{
len = stringBuilder.length() / 8 + 1;
}
byte[] huffmanCodeBytes = new byte[len];
int index = 0;
for(int i = 0; i < stringBuilder.length();i+=8){
String strByte;
if(i+8 > stringBuilder.length()){
strByte = stringBuilder.substring(i);
}else{
strByte = stringBuilder.substring(i, i+8);
}
huffmanCodeBytes[index] = (byte)Integer.parseInt(strByte, 2);
index++;
}
return huffmanCodeBytes;
}
static Map<Byte, String> huffmanCodes = new HashMap<Byte,String>();
static StringBuilder stringBuilder = new StringBuilder();
private static Map<Byte, String> getCodes(Node root){
if(root == null){
return null;
}
getCodes(root.left, "0", stringBuilder);
getCodes(root.right, "1", stringBuilder);
return huffmanCodes;
}
private static void getCodes(Node node, String code, StringBuilder stringBuilder){
StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
stringBuilder2.append(code);
if(node != null){
if(node.data == null){
getCodes(node.left, "0", stringBuilder2);
getCodes(node.right, "1", stringBuilder2);
}else{
huffmanCodes.put(node.data, stringBuilder2.toString());
}
}
}
private static void preOrder(Node root){
if(root != null){
root.preOrder();
}else{
System.out.println("赫夫曼树为空");
}
}
private static List<Node> getNodes(byte[] bytes){
ArrayList<Node> nodes = new ArrayList<Node>();
Map<Byte, Integer> counts = new HashMap<>();
for(byte b : bytes){
Integer count = (Integer) counts.get(b);
if(count == null){
counts.put(b, 1);
}else{
counts.put(b, count + 1);
}
}
for(Map.Entry<Byte, Integer> entry: counts.entrySet()){
nodes.add(new Node(entry.getKey(), entry.getValue()));
}
return nodes;
}
private static Node createHuffmanTree(List<Node> nodes){
while (nodes.size() > 1){
Collections.sort(nodes);
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
Node parent = new Node(null, leftNode.weight + rightNode.weight);
parent.left = leftNode;
parent.right = rightNode;
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parent);
}
return nodes.get(0);
}
}
class Node implements Comparable<Node>{
Byte data;
int weight;
Node left;
Node right;
public Node(Byte data, int weight){
this.data = data;
this.weight = weight;
}
@Override
public int compareTo(Node o) {
return this.weight = o.weight;
}
@Override
public String toString() {
return "Node [data=" + data + ", weight=" + weight + "]";
}
public void preOrder(){
System.out.println(this);
if(this.left != null){
this.left.preOrder();
}
if(this.right != null){
this.right.preOrder();
}
}
}