哈夫曼树的生成
哈夫曼树又叫做最优二叉树,是一种带权值路径最短的树,这种树在信息检索等方面都很重要。构造哈夫曼树的方法很多,而且你也可以构造出你自己定义的树,下面是我构造哈夫曼树的方法。
首先,把树上的每个节点定义为一个类,我的定义如下:
public class treeNode { //定义节点的属性,下面是必须有的,你也可以根据需呀定义更多 private treeNode parent; //上一个节点(父节点) private treeNode childLeft; //子节点为左节点 private treeNode childRight; //子节点的为右节点 private int value;//该节点的权值,主要是根据它来构造树 //重载构造方法,在创建对象时必须传入value数据 public treeNode(int value){ this.value=value; } //设置是一个父节点的方法(即上一个节点) public void setParent(treeNode parent){ this.parent=parent; } ///获得上一个节点的方法 public treeNode getParent(){ return parent; } //设置子节点(左节点)的方法 public void setChildLeft(treeNode childLeft){ this.childLeft=childLeft; } //获得子节点(左节点)的方法 public treeNode getChildLeft(){ return childLeft; } //设置子节点(左节点)的方法 public void setChildRight(treeNode childRight){ this.childRight=childRight; } //获得子节点(左节点)的方法 public treeNode getChildRight(){ return childRight; } //设置权值的方法 public void setValue(int value){ this.value=value; } //获得权值的方法 public int getValue(){ return value; } }
****************************************************
节点类定义好了之后,就可以开始建立树了,这里要说的是,我们是通过已知的权值创建的节点只用作这个树的叶节点。根据这点,下面是我创建树的思想,
首先根据给定的权值数组,把它进行排序,先排序可以减少后面再进行的工作,排序的方法很多,可以用冒泡排序法,也可以用插入排序法,或者其他的,我用的是冒泡排序法,而且在排序的过程中,同时创建出节点对象,并且把它们装入队列中。代码如下:
//冒泡法对数组进行排序,即对权值进行排序,按从小到大进行排序,同时封装成节点,装入队列中,list是创建的一个队列对象 public void sortValue(int[] array){ //冒泡排序的过程 for(int i=0;i<array.length;i++){ for(int j=i+1;j<array.length;j++){ if(array[i]>array[j]){//比较大小 int temp=array[i]; array[i]=array[j]; array[j]=temp; } } //创建节点对象,并把它装入队列中 treeNode node=new treeNode(array[i]); list.add(node); } } //冒泡法对数组进行排序,即对权值进行排序,按从小到大进行排序,同时封装成节点,装入队列中,list是创建的一个队列对象 public void sortValue(int[] array){ //冒泡排序的过程 for(int i=0;i<array.length;i++){ for(int j=i+1;j<array.length;j++){ if(array[i]>array[j]){//比较大小 int temp=array[i]; array[i]=array[j]; array[j]=temp
**************************************************
建树的过程很简单,就是从队列中取出权值最小的两个节点,然后再根据这两个节点创建它们的上一个节点。然后再将这个节点放入队列中(时放入相应的位置),建树的代码如下:
//生成哈夫曼树的方法 public void createTree(int[] array){ //调用sortValue方法,将叶子节点进行封装 this.sortValue(array); //根据哈夫曼编码的原理,建立哈夫曼树 while(list.size()>1){//节点树大于一时,才进行如下操作 treeNode leftnode=list.remove(0);//获得左节点 treeNode rightnode=list.remove(0);//获得右节点 //根据这两个节点,创建它们的父节点 int value=leftnode.getValue()+rightnode.getValue(); treeNode parentnode=new treeNode(value); //给这三个节点建立对应的关系 leftnode.setParent(parentnode); rightnode.setParent(parentnode); parentnode.setChildLeft(leftnode); parentnode.setChildRight(rightnode); //将这两个节点的父节点装入队列中,并对它们进行排列 this.sortAgain(parentnode); } }
*******************************************************
上面的sortAgain方法就是如何将新节点放入相应的位置,具体代码如下:
public void sortAgain(treeNode newnode){ //因为里面的节点已经排好序了,所以只是将新节点插入对应的位置就可以了 int size=list.size(); if(size>0){//里面至少有一个节点才能进行比较 if(newnode.getValue()>list.get(size-1).getValue()){//如果要加入的节点的权值大于队列中最后一个节点的权值,则放到最后面 list.add(newnode); }else{//否则才去进行比较 for(int i=0;i<list.size();i++){ treeNode node=list.get(i);//按顺序得到节点 if(newnode.getValue()<=node.getValue()){//比较它们的权值 list.add(i, newnode);//将新节点添加到指定的位置 break;//结束循环 } } } }else{//否则直接加进去 list.add(newnode); } }
}这个方法很简单,但是它能够确保新添加的节点是位于节点在左边,即代分枝的节点总在左边。