首先Huffman的原理,即每次选取出现次数最少的两个建立一颗新树,然后再循环,由此可知,一共需要循环n-1次,n即总的节点数,就可以建立起一颗Huffman树。
了解了原理后,现在来看代码:(主要以建立Huffman编码树的例子来讲)
1、首先,要建立树结点,来储存一些必要的信息。
public static class HuffmanNode{
public char data;//节点的内容
public int time;//该节点出现的次数
public HuffmanNode left;//左孩子
public HuffmanNode right;//右孩子
public int ceng=0;//层数,用于直观显示
}
2、进行构造
//构造HuffmanTree的初始化函数
public static HuffmanNode initHuffmanTree(int times[],char []datas ){
int n=times.length;
HuffmanNode huffmanNodes[]=new HuffmanNode[n];
HuffmanNode[] temp=new HuffmanNode[n];
for(int i=0;i<n;i++){
temp[i]=new HuffmanNode();
huffmanNodes[i]=new HuffmanNode();
huffmanNodes[i].data=datas[i];
huffmanNodes[i].time=times[i];
huffmanNodes[i].left=null;
huffmanNodes[i].right=null;
}
//先对整体排次序(本代码采用归并排序,且降序排列)
sort(huffmanNodes, 0, n-1, temp);
//进行n-1次的构造
for(int i=n-1;i>=1;i--){
//当前最小
HuffmanNode min1=huffmanNodes[i];
HuffmanNode min2=huffmanNodes[i-1];
HuffmanNode newNode=new HuffmanNode();
huffmanNodes[i]=null;
newNode.data='$';
newNode.time=min1.time+min2.time;
newNode.left=min1;
newNode.right=min2;
huffmanNodes[i-1]=newNode;
//对剩下的再进行排序
sort(huffmanNodes, 0, i-1, temp);
}
return huffmanNodes[0];
}
注:传入参数:times就是题目所给的各个叶子节点的出现次数,datas指各个叶子节点的内容。
排序方法多种多样,只要实现降序排列即可。为什么要降序?因为本代码采用的思想是:每次选取最后面的两个,即最小值和次小值,然后就把新生成的节点放在次小值位置上,最小值位置置为null,只要从后往前循环结束后,下标0处即最终的根节点
3、排序方法:给出归并排序的实现
//归并排序的两个方法1
private static void sort(HuffmanNode[] huffmanNodes,int left,int right,HuffmanNode []temp){
if(left<right){
int middle=(left+right)/2;
sort(huffmanNodes, left, middle, temp);
sort(huffmanNodes, middle+1, right, temp);
merge(huffmanNodes, left, right, middle, temp);
}
}
//归并排序的两个方法2
private static void merge(HuffmanNode[] huffmanNodes,int left,int right,int middle,HuffmanNode []temp){
int i=left;
int j=middle+1;
int t=0;
while(i<=middle && j<=right){
if(huffmanNodes[i].time>=huffmanNodes[j].time){
temp[t++]=huffmanNodes[i++];
}
if(huffmanNodes[i].time<huffmanNodes[j].time){
temp[t++]=huffmanNodes[j++];
}
}
while(i<=middle){
temp[t++]=huffmanNodes[i++];
}
while(j<=right){
temp[t++]=huffmanNodes[j++];
}
t=0;
while(left<=right){
huffmanNodes[left++]=temp[t++];
}
}
4、最终按照层序遍历将树遍历出来。在遍历的过程中,给其层数赋值,即父亲节点层数加一
//层序遍历HuffmanTree
public static void show(HuffmanNode root){
Queue<HuffmanNode> queue=new LinkedList<>();
root.ceng=0;
System.out.println(root.data+" "+root.time+" "+root.ceng);
if(root.left!=null) {
root.left.ceng=root.ceng+1;
queue.add(root.left);
}
if(root.right!=null) {
root.right.ceng=root.ceng+1;
queue.add(root.right);
}
while(queue.size()!=0){
HuffmanNode huffmanNode=queue.poll();
System.out.println(huffmanNode.data+" "+huffmanNode.time+" "+huffmanNode.ceng);
if(huffmanNode.left!=null) {
huffmanNode.left.ceng=huffmanNode.ceng+1;
queue.add(huffmanNode.left);
}
if(huffmanNode.right!=null) {
huffmanNode.right.ceng=huffmanNode.ceng+1;
queue.add(huffmanNode.right);
}
}
}
5、主要功能已经完成,将以上所有代码均放入道HuffmanTree类中,然后新建主函数测试
public class Main {
public static void main(String args[]){
int times[]={3 ,4, 10, 8, 6 ,5};
char datas[]={'A','B','C','D','E','F'};
HuffmanTree.HuffmanNode root=HuffmanTree.initHuffmanTree(times, datas);
HuffmanTree.show(root);
}
}
6、结果:$表示是自己添加的节点 输出格式为: data time 层数
$ 36 0
$ 15 1
$ 21 1
$ 7 2
D 8 2
C 10 2
$ 11 2
A 3 3
B 4 3
F 5 3
E 6 3