簡單介紹;
哈弗曼編碼(前綴編碼):---哈夫曼樹(最優二叉樹)可以得到前綴編碼,字符串的二進制編碼,不是固定長度的,對於詞頻高的可以短編碼,詞頻低的可以長編碼,可以壓縮數據,用於通信。前綴編碼:更準確的譯碼,一個字符的編碼不是另一個的前綴。利用二叉樹來設計前綴編碼,左0右1
算法思想:
目的是:得到一個帶權值的wpl(帶權路徑長度最小),每次把權值最小的兩棵樹合併,直到形成一個二叉樹
class Node implements Comparable<Node>{
int freq;
Integer ch;
Node left,right;
boolean isleaf;
public Node(Integer ch,int freq) {
this.freq = freq;
this.ch = ch;
this.isleaf = true;
}
public Node(Node left,Node right,int freq) {
this.left = left;
this.right = right;
this.freq = freq;
this.isleaf = false;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return this.freq-o.freq;
}
}
class HuffmanTree{
//傳一個map(字符,詞頻),得到編碼
public Map<Integer,String> encode(Map<Integer,Integer> frequencyForChar){
//先放入優先隊列進行處理,處理後得到哈夫曼樹,但是還沒有帶上01編碼,有一個函數處理,返回函數的值
PriorityQueue<Node> p = new PriorityQueue<Node>();
for (Integer c : frequencyForChar.keySet()) {
p.add(new Node(c,frequencyForChar.get(c)));
}
while(p.size()!=1) {
Node node1 = p.poll();
Node node2 = p.poll();
p.add(new Node(node1,node2,node1.freq+node2.freq));
}
return encodeReal(p.poll());
}
private Map<Integer, String> encodeReal(Node root) {
// TODO Auto-generated method stub
//盛放字符所對應的編碼
Map<Integer,String> encodingForChar = new HashMap<>();
//具體編碼用函數實現,傳入map實現回調
encodeChar(root,"",encodingForChar);
return encodingForChar;
}
private void encodeChar(Node root, String encoding,
Map<Integer, String> encodingForChar) {
// TODO Auto-generated method stub
if(root.isleaf) {
encodingForChar.put(root.ch,encoding);
return;
}
encodeChar(root.left, encoding+"0", encodingForChar);
encodeChar(root.right, encoding+"1", encodingForChar);
}
}
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
int count = in.nextInt();
map.put(count, count);
}
HuffmanTree ht = new HuffmanTree();
Map<Integer,String> encode = ht.encode(map);
for (Entry<Integer, String> s : encode.entrySet()) {
System.out.println(s.getKey()+":"+s.getValue());
}
in.close();
}
}