1. 程式人生 > >14.Huffman(哈夫曼)編碼

14.Huffman(哈夫曼)編碼

首先宣告一下,我感覺這個演算法它的程式碼有點複雜,等一下我寫的時候你就知道了。但是在理解上來說很簡單,這就是它最矛盾的地方!!

1.問題解析

由上圖可以看出每個字元在檔案中出現的次數(頻率)以及編碼方式,本題研究的就是實現最優字元編碼,要求編碼檔案所需位元數目最少。就像上圖,對於定長編碼字來說:(45+13+12+16+9+5)*3=300;對於變長編碼字來說:(45*1+13*3+12*3+16*3+9*4+5*4)=224;所以變長編碼的所需總位元數比定長編碼更優

2.編碼定義

圖中所示:每個字母旁邊的數字為其頻數,兩個父母的父節點數值由兩個子節點數值相加得到。同時一個父節點的左邊子節點編號為0,右邊子節點編號為1,如圖中所示,a編碼為:000,或0,。

3.貪婪選擇

由上圖所示,先選取字元中頻數最小的兩個組合成二叉樹,其父節點數值為兩頻數之和,然後以父節點的數值來替代原來兩個點,放入原字元頻數陣列中,再選取字元中頻數最小的兩個組合成二叉樹,直到所有的字元都在同一棵二叉樹上。然後由字元所在位置的編碼就是題目要求的最優編碼

輸入:字符集C及頻數f(C)

輸出:實現最優編碼方式時的各字元編碼

演算法虛擬碼:

HUFFMAN(C)

1.    n<-|C|

2.    Q<-C

3.    for i<- 1 to n-1

4.      do 分配新的節點z

5.          left[z]<-x<-EXTRACT-MIN(Q)

6.          right[z]<-y<-EXTRACT-MIN(Q)

7.          f[z]<-f[x]+f[y]

8.          INSERT(Q,z)

9.    return EXTRACT-MIN(Q) //返回樹的根

JAVA:

Binarytree.java

package Jamin;

public class Binarytree implements Comparable<Binarytree>{ int key; char data; Binarytree left; Binarytree right; public Binarytree() {} public Binarytree(int k,char d,Binarytree l,Binarytree r) {//將輸入的值賦值到建立的結構變數中     key=k;     data=d;     left=l;     right=r; } public String toString() {//用來做後期列印     return "Character:"+data+" frequency:"+key;  } public int compareTo(Binarytree x) {// 比較     if(key>x.key)         return 1;     if(key<x.key)         return -1;     return 0; } public void inorderwalk() {//呼叫遍歷輸出     if(left!=null)         left.inorderwalk();     System.out.print(toString());     if(right!=null)         right.inorderwalk(); } }  

Huffman.java

package Jamin; import java.util.PriorityQueue; public class Huffman { public static Binarytree huffman(int[] f,char[] d) {     int i,n=f.length;     PriorityQueue<Binarytree> Q=new PriorityQueue<Binarytree>(n);     for(i=0;i<n;i++) {         Binarytree t=new Binarytree(f[i],d[i],null,null);         Q.add(t);     }     for(i=0;i<n-1;i++) {         Binarytree x,y,z;         x=Q.poll();//從優先佇列中彈出最小值         y=Q.poll();         z=new Binarytree(x.key+y.key,'*',x,y);         Q.add(z);     }     return Q.poll();     } public static void printcode(Binarytree t,String c) {     if(t.left!=null)//向左邊搜尋,變0         printcode(t.left,c+"0");     if(t.right!=null)//向右邊搜尋,變1         printcode(t.right,c+"1");     if(t.left==null&&t.right==null)         System.out.println(t+" code:"+c+" "); } }  

Test.java

package Jamin;

public class Test {

    public static void main(String[] args) {         // TODO Auto-generated method stub int f[]= {45,13,12,16,9,5},i; char d[]= {'a','b','c','d','e','f'}; Binarytree h=Huffman.huffman(f, d); Huffman.printcode(h, ""); System.out.println(); } } 輸出結果:

Character:a frequency:45 code:0  Character:c frequency:12 code:100  Character:b frequency:13 code:101  Character:f frequency:5 code:1100  Character:e frequency:9 code:1101  Character:d frequency:16 code:111