数据结构——哈夫曼二叉树
上一篇博客中我们实现了一个简单的表达式二叉树
今天我们来实现一个哈夫曼二叉树又称最优二叉树
哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
实现原理其实很简单对于某一些场景来说,某一个区间段情况出现的机率是大很多的,比如成绩处于中游水平的人肯定是占大多数的,因此我们在取得这些数据时,如果按等概率去读取会影响程序效率
所以我们可以利用哈夫曼二叉树来实现这一效率的提升
以一个字符串为例构造哈夫曼二叉树
其实实现方法非常简单
第一步:统计字符串中各个字母出现次数,并且生成节点
第二步:根据节点的权值排序
第三步:取出权限最小的两个节点,构建一个新节点
第四步:重复2 3,直到只剩一个节点,该节点就是根节点。
首先我们还是需要一个节点类,具有左右子节点属性,以及数据域,和权值属性
public class Node {
private Node left=null;
private Node right=null;
private String str;
private int value;
public Node(){
this.str="";
}
public Node(String str,int value){
this.str=str;
this.value=value;
}
public Node(String str,Node left,Node right){
this.left=left;
this.right=right;
this.str=str;
this.value=left.value+right.value;
}
}
三个构造方法分别用来创建空节点,根节点,以及根据数据和左右子节点创建节点
然后分别设置属性的set和get方法
再新建HuffmaTree类,除了根节点属性之外还可以用一个字符串来存储哈夫曼编码所构成的01串
public class HuffmaTree {
private Node root;//根节点属性
private String str="";//用来存储01哈夫曼编码串
}
使用构造方法建树
具体过程可以参考如下代码:
public HuffmaTree(String str) {
int[] count = new int[128];// 定义存储权值的数组
ArrayList<Node> nodeList = new ArrayList<Node>();
// 遍历得到对应字符的权值
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
count[ch]++;
}
//得到具有权值的节点数组队列
for(int j=0;j<count.length;j++){
char si=(char)j;
//将具有权值的节点添加到数组队列
if(count[j]>0){
Node node=new Node(String.valueOf(si), count[j]);
nodeList.add(node);
}
}
ArrayList<Node> no=mp(nodeList);//第一次排序
for(int i=0;i<no.size();i++){
Node nod=no.get(i);
System.out.println("str:"+nod.getStr()+" value:"+nod.getValue());
}
while(no.size()>1){
//取出权值最小的两个节点
Node left=no.remove(0);
Node right=no.remove(0);
//根据最小的两个节点生成父节点
Node father=new Node(left.getStr()+right.getStr(), left, right);
no.add(father);//将新建的节点加入队列
mp(no);//每次加入父节点之后都进行一次排序
for(int i=0;i<no.size();i++){
Node nod=no.get(i);
System.out.println("str:"+nod.getStr()+" value:"+nod.getValue());
}
}
root=no.get(0);//存储权值最大的根节点
}
其实就是不停的取出权值最小的节点,以及将新产生的节点存入队列,排序之后重复建节点。
这样我们就将一个字符串生成了一颗哈夫曼二叉树,不过还是建议遍历二叉树验证一下结果。