1、赫夫曼编码概念
是一种编码方式,属于一种程序算法。 广泛用于数据文件的压缩,其压缩率在20%~90%左右。
一般的编码流程:字符串 => ASCLL编码 => 二进制
编码发展过程:定长编码(8位,不进行处理)=>变长编码(减少长度,但是有多异性) => Hefuman编码(将频率作为权重,进行哈弗曼编码))
2、赫夫曼编码思路
1、先总结每个字符使用频率,并存入节点(str => bytes => Map => list)
2、将频率作为权值,将每个字符作为叶子节点,构建赫夫曼树
3、将赫夫曼树每个节点(非叶子节点)的左边分支标为0,右边分支标为1。那么,从根节点到叶子节点的分支上的数字组合就是该叶子节点(字符)的赫夫曼编码值。
- 代码:
package tree.huffmanTree;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.activation.MailcapCommandMap;
public class HuffmanTreeCode {
static Map<Byte, StringBuilder> hashMap = new HashMap<Byte, StringBuilder>();
static StringBuilder stringBuilder = new StringBuilder();
public static void main(String[] args) {
// TODO Auto-generated method stub
//哈夫曼编码:
//构建哈夫曼树节点,包括data(byte),weigth(频率),leftNode,rightNode等
//然后待编译的字符串存放在bytes数组中,并通过map将byte存放在list数组中。
//构建赫夫曼树
HuffmanTreeCode huffmanTreeCode = new HuffmanTreeCode();
String string = "I like like like like like java and do you like it";
byte[] bytes = string.getBytes();
ArrayList<HuffmanTreeNode1> list = huffmanTreeCode.getList(bytes);
HuffmanTreeNode1 huffmanTreeNode1 = huffmanTreeCode.buildHuffmanTree(list);
// System.out.println(Arrays.toString(bytes));
// System.out.println(list);
//
huffmanTreeCode.preOrder(huffmanTreeNode1);
huffmanTreeCode.hfmCode(huffmanTreeNode1,"",stringBuilder);
System.out.println(hashMap);
}
//将bytes转化为list
public ArrayList<HuffmanTreeNode1> getList(byte[] bytes){
ArrayList<HuffmanTreeNode1> list = new ArrayList<HuffmanTreeNode1>();
Map<Byte, Integer> hashMap = new HashMap<>();
Integer lenght;
for (int i = 0; i < bytes.length; i++) {
lenght = hashMap.get(bytes[i]);
if(lenght == null) {
hashMap.put(bytes[i], 1);
}else {
hashMap.put(bytes[i], lenght+1);
}
}
for(Map.Entry<Byte, Integer> entry : hashMap.entrySet()) {
list.add(new HuffmanTreeNode1(entry.getKey(),entry.getValue()));
}
return list;
}
//构建哈夫曼树
public HuffmanTreeNode1 buildHuffmanTree(ArrayList<HuffmanTreeNode1> list) {
HuffmanTreeNode1 pareNode;
while(list.size() > 1) {
//排序
Collections.sort(list);
//先取出两个最小的元素
pareNode = new HuffmanTreeNode1(null, list.get(0).getWeigth()+list.get(1).getWeigth());
pareNode.setLeftNode(list.get(0));
pareNode.setRightNode(list.get(1));
list.remove(0);
list.remove(0);
list.add(pareNode);
System.out.println(pareNode.toString());
}
return list.get(0);
}
//前序遍历
public void preOrder(HuffmanTreeNode1 node) {
if(node == null) {
return;
}
node.preOrder();
}
//
//hfm编码
public void hfmCode(HuffmanTreeNode1 node, String aString, StringBuilder stringBuilder) {
StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
stringBuilder2.append(aString);
//判断是不是叶子节点
if(node.getData() == null) {//非叶子节点
hfmCode(node.getLeftNode(), "0", stringBuilder2);
hfmCode(node.getRightNode(), "1", stringBuilder2);
}else {
hashMap.put(node.getData(), stringBuilder2);
}
}
}
class HuffmanTreeNode1 implements Comparable<HuffmanTreeNode1>{
private Byte data;
private Integer weigth;
private HuffmanTreeNode1 leftNode;
private HuffmanTreeNode1 rightNode;
public HuffmanTreeNode1(Byte data, int weigth ) {
this.data = data;
this.weigth = weigth;
}
public Byte getData() {
return data;
}
public void setData(byte data) {
this.data = data;
}
public int getWeigth() {
return weigth;
}
public void setWeigth(int weigth) {
this.weigth = weigth;
}
public HuffmanTreeNode1 getLeftNode() {
return leftNode;
}
public void setLeftNode(HuffmanTreeNode1 leftNode) {
this.leftNode = leftNode;
}
public HuffmanTreeNode1 getRightNode() {
return rightNode;
}
public void setRightNode(HuffmanTreeNode1 rightNode) {
this.rightNode = rightNode;
}
@Override
public String toString() {
return "HuffmanTreeNode1 [data=" + data + ", weigth=" + weigth + "]";
}
//前序遍历
public void preOrder() {
System.out.println(this.toString());
if(this.leftNode != null) {
this.leftNode.preOrder();
}
if(this.rightNode != null) {
this.rightNode.preOrder();
}
}
@Override
public int compareTo(HuffmanTreeNode1 o) {
// TODO Auto-generated method stub
return this.getWeigth() - o.getWeigth();//升序
}
}