首先声明一下,我感觉这个算法它的代码有点复杂,等一下我写的时候你就知道了。但是在理解上来说很简单,这就是它最矛盾的地方!!
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) //返回树的根
Binarytree.java
package Jamin;
public class Binarytree implements Comparable
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
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
for(i=0;i
Q.add(t);
}
for(i=0;i
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