霍夫曼编码
package algorithm;
import java.util.*;
public class HuffmanEncode {
public static void main(String[] args) {
String str = "i like like like algorithm";
byte[] res = huffmanZip(str);
}
private static byte[] huffmanZip(String data){
byte[] bytes = data.getBytes();
Map<Byte, Integer> bytesMap = new HashMap();
for (byte b : bytes) {
if (bytesMap.containsKey(b)) {
Integer count = bytesMap.get(b);
bytesMap.put(b, count + 1);
} else {
bytesMap.put(b, 1);
}
}
List<Node> nodes = new ArrayList<>();
for (Map.Entry<Byte, Integer> element : bytesMap.entrySet()) {
nodes.add(new Node(element.getValue(), element.getKey()));
}
Node root = generateHuffmanTree(nodes);
preOrder(root);
Map<Byte, String> huffmanCodesMap = new HashMap<>();
generateHuffmanCode(root, "", "", huffmanCodesMap);
System.out.println("Huffman code : " + huffmanCodesMap);
byte[] huffmanCodesByte = zip(bytes, huffmanCodesMap);
System.out.println(Arrays.toString(huffmanCodesByte));
return huffmanCodesByte;
}
private static byte[] zip(byte[] bytes, Map<Byte, String> huffmanCodesMap) {
StringBuffer sb = new StringBuffer();
for (byte b : bytes) {
sb.append(huffmanCodesMap.get(b));
}
int len = (sb.length() + 7) / 8;
byte[] huffmanCodesByte = new byte[len];
for (int i = 0, index = 0; i < sb.length(); i += 8, index++) {
String temp;
if(i + 8 > sb.length()){
temp = sb.substring(i);
}else{
temp = sb.substring(i, i+8);
}
huffmanCodesByte[index] = (byte) Integer.parseInt(temp,2);
}
return huffmanCodesByte;
}
private static void generateHuffmanCode(Node node, String path, String code, Map<Byte, String> huffmanCodesMap) {
if (node == null) {
return;
}
String newCode = code + path;
if (node.data == null) {
if (node.left != null) {
generateHuffmanCode(node.left, "0", newCode, huffmanCodesMap);
}
if (node.right != null) {
generateHuffmanCode(node.right, "1", newCode, huffmanCodesMap);
}
} else {
huffmanCodesMap.put(node.data, newCode);
}
}
private static Node generateHuffmanTree(List<Node> nodes) {
if (nodes.size() == 0) {
return null;
}
while (nodes.size() > 1) {
Collections.sort(nodes);
Node left = nodes.get(0);
Node right = nodes.get(1);
Node parent = new Node(left.value + right.value, null);
parent.left = left;
parent.right = right;
nodes.remove(left);
nodes.remove(right);
nodes.add(parent);
}
return nodes.get(0);
}
public static void preOrder(Node node) {
if (node != null) {
node.preOrder();
} else {
System.out.println("Tree is empty.");
}
}
}
class Node implements Comparable<Node> {
int value;
Byte data;
Node left;
Node right;
public Node(int value, Byte data) {
this.value = value;
this.data = data;
}
public void preOrder() {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
@Override
public int compareTo(Node o) {
return this.value - o.value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
", data=" + data +
'}';
}
}