哈夫曼编码:
在信息传输中,若按照ascii码进行表示,每一个码表示一个字符,总体上需要的码长较长
为了实现数据的压缩传输,利用数据出现的频率,进行哈夫曼编码,让出现频率高的字符编码长度较短,而出现频率低的字符编码长度较长,从而让总体码长较短
实现思路:
统计待传输信息中的各个字符出现次数,并以此作为树节点的权值,构建各个字符组成的哈夫曼树
显然各个字符节点都是叶子节点,从根节点出发,规定向左的路径编码0,向右的路径编码1,对于任意一个字符的哈夫曼编码,只需要连接根节点与该字符节点,并将路径上的编码合成一个大的编码即可
对于哈夫曼编码的生成,通过递归实现,分别向左、向右递归并让编码加上对应的路径码,直到找到叶子节点,将该叶子节点代表的字符和对应的编码存入hashmap中
代码实现:
节点类HuffmanCodingNode:
public class HuffmanCodingNode implements Comparable<HuffmanCodingNode> {
public Character data;
public int weight;
public HuffmanCodingNode left;
public HuffmanCodingNode right;
public HuffmanCodingNode(Character data, int weight) {
this.data = data;
this.weight = weight;
}
@Override
public String toString() {
return "HuffmanCodingNode{" + "data=" + data + ", weight=" + weight + '}';
}
@Override
public int compareTo(HuffmanCodingNode o) {
return this.weight - o.weight;
}
}
哈夫曼树类HuffmanCoding:
public class HuffmanCoding {
public HuffmanCodingNode root;
public Map<Character, String> huffmanCodes = new HashMap<>();
public HuffmanCoding(String str) {
List<HuffmanCodingNode> nodes = new ArrayList<>();
Map<Character, Integer> counts = new HashMap<>();
char[] strArray = str.toCharArray();
Integer count;
for (char c : strArray) {
count = counts.get(c);
if (count == null) {
counts.put(c, 1);
} else {
counts.put(c, count + 1);
}
}
for (Map.Entry<Character, Integer> entry : counts.entrySet()) {
nodes.add(new HuffmanCodingNode(entry.getKey(), entry.getValue()));
}
while (nodes.size() > 1) {
Collections.sort(nodes);
HuffmanCodingNode leftNode = nodes.get(0);
HuffmanCodingNode rightNode = nodes.get(1);
HuffmanCodingNode parentNode = new HuffmanCodingNode(null, leftNode.weight + rightNode.weight);
parentNode.left = leftNode;
parentNode.right = rightNode;
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parentNode);
}
root = nodes.get(0);
}
//生成哈夫曼编码
public void getHuffmanCodes() {
getHuffmanCodes(root, "", new StringBuilder());
}
public void getHuffmanCodes(HuffmanCodingNode node, String code, StringBuilder stringBuilder) {
StringBuilder newStringBuilder = new StringBuilder(stringBuilder);
newStringBuilder.append(code);
if (node != null) {
if (node.data == null) {
getHuffmanCodes(node.left, "0", newStringBuilder);
getHuffmanCodes(node.right, "1", newStringBuilder);
} else {
huffmanCodes.put(node.data, newStringBuilder.toString());
}
}
}
}