最佳实践-数据压缩(创建赫夫曼树)
将给出的一段文本,比如 "i like like like java do you like a java" , 根据前面的讲的赫夫曼编码原理,对其进行数据压缩处理 ,形式如 "1010100110111101111010011011110111101001101111011110100001100001110011001111000011001111000100100100110111101111011100100001100001110"
步骤1:根据赫夫曼编码压缩数据的原理,需要创建 "i like like like java do you like a java" 对应的赫夫曼树.
思路:前面已经分析过了,而且我们已然讲过了构建赫夫曼树的具体实现。
最佳实践-数据压缩(生成赫夫曼编码和赫夫曼编码后的数据)
1)生成赫夫曼树对应的赫夫曼编码 , 如下表:
=01 a=100 d=11000 u=11001 e=1110 v=11011 i=101 y=11010 j=0010 k=1111 l=000 o=0011
2)使用赫夫曼编码来生成赫夫曼编码数据 ,即按照上面的赫夫曼编码,将"i like like like java do you like a java" 字符串生成对应的编码数据, 形式如下.
1010100010111111110010001011111111001000101111111100100101001101110001110000011011101000111100101000101111111100110001001010011011100
使用赫夫曼编码来解码数据,具体要求是
代码实现:
package com.liu.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(); List<Node> nodes = getNodes(contentBytes);
* System.out.println("nodes=" + nodes); System.out.println("赫夫曼树"); Node
* huffmanTreeRoot = creatHuffManCode(nodes); System.out.println("前序遍历");
* huffmanTreeRoot.preOrder();
*
* Map<Byte, String> huffmanCodes = getCode(huffmanTreeRoot);
* System.out.println("~生成的赫夫曼编码表= " + huffmanCodes);
*
* byte[] huffmanCodeBytes = zip(contentBytes , huffmanCodes);
* System.out.println("huffmanCodeBytes=" +
* Arrays.toString(huffmanCodeBytes));//17
*/
String content = "i like like like java do you like a java";
byte[] contentBytes = content.getBytes();
System.out.println(contentBytes.length); //40
byte[] huffmanCodesBytes= huffmanzip(contentBytes);
System.out.println("压缩后的结果是:" + Arrays.toString(huffmanCodesBytes) + " 长度= " + huffmanCodesBytes.length);
//测试一把byteToBitString方法
//System.out.println(byteToBitString((byte)1));
byte[] sourceBytes = deCode(huffmanCode, huffmanCodesBytes);
System.out.println("原来的字符串=" + new String(sourceBytes)); // "i like like like java do you like a java"
}
public static byte[] deCode(Map<Byte, String> huffmanCodes, byte[] bytes) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
stringBuilder.append(byteToString((i != bytes.length - 1), bytes[i]));
}
Map<String, Byte> map = new HashMap<String, Byte>();
for (Map.Entry<Byte, String> entry : huffmanCodes.entrySet()) {
map.put(entry.getValue(), entry.getKey());
}
List<Byte> lists = new ArrayList<Byte>();
for (int i = 0; i < stringBuilder.length();) {
int count = 1;
boolean flag = false;
Byte b = null;
while (!flag) {
String key = stringBuilder.substring(i, i + count);
b = map.get(key);
if (b != null) {
flag = true;
} else {
count++;
}
}
i += count;
lists.add(b);
}
byte b[] = new byte[lists.size()];
for (int i = 0; i < b.length; i++) {
b[i] = lists.get(i);
}
return b;
}
public static String byteToString(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;
}
}
public static byte[] huffmanzip(byte[] bytes) {
List<Node> nodes = getNodes(bytes);
Node huffmanTreeRoot = creatHuffManCode(nodes);
huffmanTreeRoot.preOrder();
Map<Byte, String> huffmanCodes = getCode(huffmanTreeRoot);
byte[] huffmanCodeBytes = zip(bytes, huffmanCodes);
return huffmanCodeBytes;
}
public static byte[] zip(byte[] bytes, Map<Byte, String> huffmanCode) {
StringBuilder stringBuilder = new StringBuilder();
for (byte b : bytes) {
stringBuilder.append(huffmanCode.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, i + 8);
} else {
strByte = stringBuilder.substring(i);
}
huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte, 2);
index++;
}
return huffmanCodeBytes;
}
static Map<Byte, String> huffmanCode = new HashMap<Byte, String>();
static StringBuilder stringBuilder = new StringBuilder();
public static Map<Byte, String> getCode(Node root) {
if (root == null) {
return null;
}
// 处理root的左子树
getCode(root.left, "0", stringBuilder);
// 处理root的右子树
getCode(root.right, "1", stringBuilder);
return huffmanCode;
}
public static void getCode(Node node, String code, StringBuilder stringBuilder) {
StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
stringBuilder2.append(code);
if (node != null) {
if (node.data == null) {
getCode(node.left, "0", stringBuilder2);
getCode(node.right, "1", stringBuilder2);
} else {
huffmanCode.put(node.data, stringBuilder2.toString());
}
}
}
public static void preOrder(Node root) {
if (root != null) {
root.preOrder();
} else {
System.out.println("赫夫曼树为空");
}
}
public static List<Node> getNodes(byte arry[]) {
List<Node> nodes = new ArrayList<Node>();
Map<Byte, Integer> counts = new HashMap<>();
for (byte b : arry) {
Integer count = 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;
}
public static Node creatHuffManCode(List<Node> nodes) {
while (nodes.size() > 1) {
Collections.sort(nodes);
Node leftnode = nodes.get(0);
Node rightnode = nodes.get(1);
Node patten = new Node(null, leftnode.value + rightnode.value);
patten.left = leftnode;
patten.right = rightnode;
nodes.remove(leftnode);
nodes.remove(rightnode);
nodes.add(patten);
}
return nodes.get(0);
}
}
class Node implements Comparable<Node> {
Byte data;
int value;
Node left;
Node right;
public Node(Byte data, int value) {
this.data = data;
this.value = value;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return this.value - o.value;
}
@Override
public String toString() {
return "Node [data=" + data + ", value=" + value + "]";
}
public void preOrder() {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
;
}
if (this.right != null) {
this.right.preOrder();
;
}
}
}