当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

哈夫曼压缩

发表于: 2012-10-30   作者:叶紫夜子   来源:转载   浏览:
摘要: 浅谈哈夫曼压缩        什么是哈夫曼压缩啊?其实,在做 之前看过前一组的一个同学做哈夫曼压缩的过程,那是我刚开始做画图板,看他写了好多,我什么都看不懂。这学期,经过龙哥的讲解,对哈夫曼压缩有了一定的了解,下面就简单的写一下自己的理解。 一、哈夫曼树       
浅谈哈夫曼压缩   
    什么是哈夫曼压缩啊?其实,在做 之前看过前一组的一个同学做哈夫曼压缩的过程,那是我刚开始做画图板,看他写了好多,我什么都看不懂。这学期,经过龙哥的讲解,对哈夫曼压缩有了一定的了解,下面就简单的写一下自己的理解。

一、哈夫曼树    
   哈夫曼树也称最优二叉树,它是将给定的n个权值作为n个节点构造的一棵二叉树,其带权路径长度最小。

二、哈夫曼编码
      哈夫曼编码是一种可变字长编码,是根据字符 出现的概率来构造平均长度最小的01串,是一种很好的编码方式。

三、压缩原理
1、哈夫曼压缩:
    哈夫曼压缩是一种无损压缩,在压缩过程中不会丢失信息,适合用于对应用程序 和重要资料进行压缩,应用十分广泛。
2、实现原理:
    就是将被压缩文件中的个体符号用一个特定长度的位序列代替。在文件中出现频率高的字符用短的位序列代替, 而那些较少出现的出现的字符用长位序列代替。
    大家都知道,计算机中的数据都是以二进制存储的,一个字节占8个“0”,“1” 位, 所以我们就可以将读取的字符进行“0”“1”编码,以计算机的存储方式用位的方法写入另一个文件就可以实现编码了。



四、压缩步骤
[size=medium]
1、统计文件中每个字节出现的次数

/**
 * 读取文件的方法,以字节的形式读取
 * @param fileName文件名
 * @return将读取的字节转化为整型返回
 */
public  int[] readFile(String fileName)
{
   try{
   //创建输出流对象
    FileInputStream ins=new FileInputStream(fileName);
    
   int i=0;
   //创建数组
    int[] array=new int [256];
       
   //统计读取的字节数
    int count=0;
   
    while((i=ins.read())!=-1)
    {
    	int j ;
         //读取
    	i=ins.read();
    	for(j=1;j<array.length;j++)
    	if(i==j)
    	{
    	//数组元素值加1
    	array[j]++;
         }
    	count ++;
     }
   //返回数组
   return array;
    }catch(Exception ef)
	{
	     return null;
	}
	
	
}

2、以次数为权值构建哈夫曼树

/**
 * 将数组中的元素作为结点存储在队列中
 * 
 * @param array传入数组
 * @return返回一个人排好序的队列
 */
public PriorityQueue<TreeNode> array2List(int[] array) {
     // 根据指定的比较器创建一个优先队列
      PriorityQueue<TreeNode> list = new PriorityQueue<TreeNode>(11,new MyComparator());
			
     // 将数组中的每一个元素都作为一个结点
      for (int i = 0; i < array.length; i++) {
	if(array[i]!=0)
	{
	// 创建结点对象
	TreeNode node = new TreeNode(array[i]);
	node.b=i;
	
	// 将结点放入队列
	list.add(node);
	}
        }
	return list;
}

/**
 * 根据传入的优先队列构造哈夫曼树
 * 
 * @param list
 * @return
 */
public TreeNode queue2Tree(PriorityQueue<TreeNode> list) {
     
          while (list.size() > 1) {
	// 从优先队列中取得前两个结点对象
	TreeNode node1 = list.poll();
	TreeNode node2 = list.poll();

	// 根据两个结点的权值和构造新结点,作为父节点
	TreeNode root = new TreeNode(node1.obj + node2.obj);

	//建立相互关系
	root.left = node1;
	root.right = node2;

	node1.parent = root;
	node2.parent = root;
		
	node1.flag=0;
	node2.flag=1;

	// 将新结点放入队列
	list.add(root);

	}

	// 取出最后一个结点,就是哈夫曼树的根结点
	TreeNode rootNode = list.poll();

	return rootNode;

}

3、根据哈夫曼树得到每个叶子节点的编码,用字符串数组存储

/**
 * 根据哈夫曼树得到每个叶子结点的哈夫曼编码
 * 
 * @param root
 * @return 将编码放在一个字符串数组中返回,数组长度是256,数组的下标对应每一个字节
 */
public String[] getHFMCodeByTree(TreeNode root) {

	String[] codes = new String[256];
	
	
	getOneNodeCode(root, codes, "");

	return codes;
}

/**
 * 递归得到每个叶结点的编码
 * 
 * @param root 哈夫曼树
 * @param codes 存放每个字节编码的字符串数组 数组下标为每个字节
 * @param num 生成的哈夫曼编码
 */
private void getOneNodeCode(TreeNode root, String[] codes, String str) {
	if (root != null) {	
            if (root.flag != null) {
		str = str + root.flag;
		if (root.left == null && root.right == null) {
		// 当递归到叶子结点的时候就把得到的字符串放到结点中的字节作为下标的位置
		codes[root.b] = str;
			}
		}
		
		//左节点
		TreeNode left = root.left;
		getOneNodeCode(left, codes, str);
                 
                  //右节点
		TreeNode right = root.right;
		getOneNodeCode(right, codes, str);

	}

}

4、将文件中的字节用对应的编码表示,得到“0”,“1”字符串
5、将字符串以每8个为一组作为二进制转换为十进制,形成一个字节
 //写入哈夫曼编码
    for(int i=0;i<codes.length;i++){
   int lenth=codes[i].length();//得懂每个哈夫曼编码的长度
    if(lenth<1){
    //如果编码为空,把长度写入
    dops.write(lenth); 	 
    }
		    	
   if(lenth>0&&lenth<8){
    //如果编码的的长度小于8,就把它转化为一个字节
     dops.write(lenth);//写入编码的长度
     byte b=Byte.parseByte(codes[i], 2);
    //写入编码
    dops.write(b);
     }
    else if(lenth>7&&lenth<32){
    //如果编码的长度大于7并且小于32,就把它转化为一个整数
    //写入编码的长度
    dops.write(lenth);
    int it=Integer.parseInt(codes[i], 2);
    //按一个整型写进去

    dops.writeInt(it);
}
6、将所有的字节写入另一个文件,该文件即为压缩后的文件[/size]

哈夫曼压缩

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
自己做过的东西,别人一问说不出一个所以然来,做了与没做也就成了一回事! 为了给自己长点记心,特
一、压缩 思路:一个文件中,都会出现重复的字节,有些字节出现的次数多,有些字节出现的次数少,这
这次压缩做的时间比较长。主要因为考试和课程设计,在暑假里要做通信,不用备考,可以一心一意的学
自己做过的东西,别人一问说不出一个所以然来,做了与没做也就成了一回事! 为了给自己长点记心,特
自己做过的东西,别人一问说不出一个所以然来,做了与没做也就成了一回事! 为了给自己长点记心,特
自己做过的东西,别人一问说不出一个所以然来,做了与没做也就成了一回事! 为了给自己长点记心,特
此文主要分析的是哈夫曼压缩的重点包括统计字符频率,建哈夫曼树,生成码表。哈夫曼压缩是最常用的
编程独白 给你40分钟的时间,你可以思考十分钟,然后用三十分钟的时间来写代码,最后浪费在无谓的调
哈夫曼压缩项目总结 最近一个月都在搞哈夫曼压缩。现在来总结一下哈夫曼压缩 在写代码之前,你要清
《哈夫曼压缩》总结 压缩: 一:压缩原理 什么是哈夫曼压缩?呵呵。。。。顾名思义。借用哈夫曼树来
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号