取得叶子结点的哈夫曼编码

在二叉树的基础上学习了哈夫曼树,创建哈夫曼树,需要比较数据之间的大小,用到了优先队列的方法,这个方法很好用,可以解决每次取出与放回结点后需要排序的问题。下面跟大家分享下 哈夫曼树的创建及如何取得每个叶子结点的哈夫曼编码。

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Random;


public class hfmList {
	private  int date[]=new int[256];//定义一个数组,存储每个字节出现的次数
	private static hufNode Root=null;//根结点初赋值为空
	
	//函数入口
	public static void main(String[] args)throws Exception {
//得到文件路径
		hfmList hfm =new hfmList("D:\\temp\\qq.txt");
//		hfmList hfm =new hfmList();
		hfm.createTree();//调用方法
		hfm.getMB(hfm.Root, "");//调用方法
	}
	
	//重载构造函数
	public hfmList(String path)throws Exception {
//创建文件输入流
		FileInputStream fis =new FileInputStream(path);
//将文件转化成缓冲流输入
		DataInputStream dis=new DataInputStream(fis);
		//读入所有的文件字节
		while(dis.available()>0){
			int i =dis.read();
			date[i]++;//记录每个字节出现的频率
		}	
	}
                /**
	 * 使用优先队列构造哈弗曼树
	 */
	public void createTree(){
		PriorityQueue<hufNode> nodeQueue = new PriorityQueue<hufNode>();
		//将所有的结点都加入到队列中去
		for(int i=0;i <date.length;i++){
			if(date[i] !=0){//字节次数不为零
                  //取出结点
		hufNode node =new hufNode(i,date[i]);
                         //将结点添加到队列中
		boolean no=nodeQueue.add(node);
		System.out.println(no);//调试加入是否成功
			}
		}
                    //构建哈弗曼树
		while (nodeQueue.size() > 1){
	hufNode min1 = nodeQueue.poll();//获取队列头
	hufNode min2 = nodeQueue.poll();//获取队列的第二个数
      //将获取的队列的前两个结点相加构成一个新结点
       hufNode result =new hufNode(0,min1.times+min2.times);
                  //设置三个结点间的关系
			result.leftchild =min1;
			result.rightchild =min2;
			min1.parent=result;
			min2.parent=result;
			nodeQueue.add(result);//加入合并结点
		}
		Root=nodeQueue.peek();//得到根结点
	}
//取得每个叶子结点的哈夫曼编码
     public void getMB(hufNode root,String s){
     if((root.leftchild == null)&& (root.rightchild==null)){//得到叶结点
    		 Code hc =new Code();
    		 hc.node=s;
    		 hc.n=s.length();
    		 System.out.println("结点"+root.date+"编码"+hc.node);
    	 }
    	 if(root.leftchild !=null){//如果不为空,则左 0 右1
    		 getMB(root.leftchild,s+'0');
    	 }
    	 if(root.rightchild !=null){
    		 getMB(root.rightchild,s+'1');
    	 }
     }
}

还需要一个结点类,我将结点类设置为哈夫曼类的内部类

   //创建结点类
     class  hufNode implements Comparable{
    	   int times;//结点的数据对象
    	  int date;//结点出现有频率
    	  hufNode parent;//定义父亲结点
    	 hufNode leftchild=null;//左结点初赋值为空
    	   hufNode rightchild =null;//右结点初赋值为空
    	//构造函数,用于传递参数
         public hufNode(int times,int date){
        	 this.times=times;
        	 this.date=date;
        	 
         }
		//重写方法,比较两个对象
		public int compareTo(Object o) {
			hufNode huf =(hufNode)o;
			return times-huf.times;//根据返回值是正数、零或负数来判断两个对象的大小
		}
}

 另外还要创建编码长度的类.本来可以不用再创建这个类的,只是这样做的话,显得条理更清晰些。

public class Code {
	String node;//编码
	int n;//编码的长度
}

 这样,我们的哈夫曼树建好啦。当然在此基础上还有很大的改进空间,任重道远啊……

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值