java 哈夫曼编码

//哈夫曼树类
public class HaffmanTree {
    //最大权值
    static final int MAXVALUE=1000;
    int nodeNum ; //叶子结点个数

    public HaffmanTree(int n)
    {
       this.nodeNum = n;
    }

    //构造哈夫曼树算法
    public void haffman(int[] weight,HaffNode[] nodes)//权值数组,所有节点数组
    {
        int n = this.nodeNum;
        //m1,m2,表示最小的两个权值,x1,x2,表示最小两个权值对应的编号,m1表示最小,m2表示次小
        int m1,m2,x1,x2; 

        //初始化所有的结点,对应有n个叶子结点的哈夫曼树,有2n-1个结点。
        for(int i=0;i < 2*n-1;i++)
        {
            HaffNode temp = new HaffNode();
            //初始化n个叶子结点,就是输入的节点。0、1、2、3是叶子节点也是输入的节点
            if(i < n)
            {
               temp.weight = weight[i];
            }
            else
            {
               temp.weight = 0;
            }
            temp.parent = 0;
            temp.flag = 0;
            temp.leftChild = -1;
            temp.rightChild = -1;
            nodes[i] = temp;
        }

        for(int i=0;i<n-1;i++){//初始化n-1个非叶子结点,n-1表示要循环n-1次求的n-1个数。
           m1 = m2 = MAXVALUE;
           x1 = x2 =0;
           for(int j=0;j< n+i;j++)//求得这n-1个数时,每次都是从0到n+i-1,并且flag=0的,flag=1表示已经加入到二叉树。
           {   //以下2步是找出权值最小的2个
               if(nodes[j].weight<m1 && nodes[j].flag==0)//if成立了else、else if就不进去了。
               {
                //m1,x1初始值为第一个元素,后面如果比m1要小,则m1指向更小的,原来m1指向的现在由m2指向,
                //如果后面比m1大比m2小,则m2指向这个比m1大比m2小的,
                //也就是说m1指向最小的,m2指向第2小的。
                  m2 = m1;
                  x2 = x1;
                  m1 = nodes[j].weight;
                  x1 = j;
               }
               else if(nodes[j].weight<m2 && nodes[j].flag ==0)
               {
                  m2 = nodes[j].weight;
                  x2 = j;
               }
           }
           //将权值最小的2个组合成一个2插树
           nodes[x1].parent = n+i;
           nodes[x2].parent = n+i;
           nodes[x1].flag = 1;
           nodes[x2].flag = 1;
           nodes[n+i].weight = nodes[x1].weight + nodes[x2].weight;
           nodes[n+i].leftChild = x1;
           nodes[n+i].rightChild = x2;
        }
        /*
        初始化数组之后:[1,3,5,7,4,9,16]
        编码:100、101、11、0
        */
    }

    //哈弗曼编码算法
    public void haffmanCode(HaffNode[] nodes,Code[] haffCode)
    {
        int n = this.nodeNum;
        Code code = new Code(n);//4
        int child,parent;

        for(int i=0;i<n; i++)//给前面n个输入的节点进行编码
        {
           code.start = n-1;//3
           code.weight = nodes[i].weight;//1
           child = i;//0
           parent = nodes[child].parent;
           //从叶子节点向上走来生成编码,画图即可。
           while(parent!=0)
           {
              if(nodes[parent].leftChild == child)
              {
                  code.bit[code.start] = 0;
              }
              else
              {
                  code.bit[code.start] = 1;
              }

              code.start--;
              child = parent;
              parent = nodes[child].parent;
           }

           Code temp = new Code(n);
           for(int j=code.start+1;j < n;j++)
           {
               temp.bit[j] = code.bit[j];
           }
           temp.weight = code.weight;
           temp.start = code.start;
           haffCode[i] = temp;
        }
    }
}

//哈夫曼树的结点类
public class HaffNode {

    int weight; //权值
    int parent ;//他的双亲
    int flag ;//标志,是否为叶子节点
    int leftChild; //他的左孩子
    int rightChild;//他的右孩子

    HaffNode()
    {

    }

}

//哈夫曼编码类
public class Code {

    int[] bit;  //编码的数组
    int start;  //编码的开始下标
    int weight; //权值
    Code(int n){
        bit = new int[n];
        start = n-1;
    }
}

public class Test {

    public static void main(String[] args) {

        int n = 4;
        int[] weight = {1,3,5,7};
        HaffmanTree haffTree = new HaffmanTree(n);
        HaffNode[] nodes = new HaffNode[2*n-1];
        Code[] codes = new Code[n];
        //构造哈夫曼树
        haffTree.haffman(weight, nodes);
        //生成哈夫曼编码
        haffTree.haffmanCode(nodes, codes);

        //打印哈夫曼编码
        for(int i=0;i<n;i++)
        {
            System.out.print("Weight="+codes[i].weight+" Code=");
            for(int j=codes[i].start+1;j<n;j++)
            {
               System.out.print(codes[i].bit[j]);
            }
            System.out.println();
        }
    }

}

哈夫曼树:

带权路径长度是做小的,要使一棵二叉树的带权路径长度WPL值最小,必须使权值越大的叶结点越靠近根结点。哈夫曼提出的构造哈夫曼树构造算法为:
(1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根 结点的二叉树,从而得到一个二叉树森林F={T1,T2,…,Tn}。
(2)在二叉树森林F中选取根结点的权值最小和次小的两棵二叉树作为新的二叉树的左右子树构造新的二叉树,新的二叉树的根结点权值为左右子树根结点权值之和。
(3)在二叉树森林F中删除作为新二叉树左右子树的两棵二叉树,将新二叉树加入到二叉树森林F中。
(4)重复步骤(2)和(3),当二叉树森林F中只剩下一棵二叉树时,这棵二叉树就是所构造的哈夫曼树。

哈夫曼编码问题:

哈夫曼树可用于构造代码总长度最短的编码方案。具体构造方法如下:
设需要编码的字符集合为{d1,d2,…,dn},各个字符在电文中出现的次数集合为{w1,w2,…,wn},以d1,d2,…,dn作为叶结点,以w1,w2,…,wn作为各叶结点的权值构造一棵二叉树,规定哈夫曼树中的左分支为0,右分支为1,则从根结点到每个叶结点所经过的分支对应的0和1组成的序列便为该结点对应字符的编码。这样的代码总长度最短的不等长编码称之为哈夫曼编码。

时间: 2024-11-08 14:30:31

java 哈夫曼编码的相关文章

java使用优先级队列实现哈夫曼编码

思路: 构建小根堆 根据小根堆实现哈夫曼树 根据哈夫曼树对数据进行编码 代码实现如下: /** * @Author: DaleyZou * @Description: 使用java实现一个哈夫曼编码的小程序 * @Date: Created in 19:45 2018-9-27 * @Modified By: */ public class HuffmanCode { private class Node implements Comparable<Node>{ char ch; // 字符

数据结构(java语言描述)哈夫曼编码

原理:哈夫曼编码是根据将已给出的权值作为叶子结点,生成一颗哈夫曼树,然后使得权重最小. 首先生成已给权重的所有的叶子结点,然后取所有节点中最小和次小的结点作为左右孩子生成一个哈夫曼树,计算出父节点的权重放入给出的权重森林中,并把之前的最小和次小的结点从森林中删除,再在种种森林中找最小和次小的结点生成权重树....直到最终只剩下一个树为止. 哈夫曼树的结点用如下结点表示: (有权重,左右孩子,父节点,然后设置一个标识符标志结点是否已经放入哈夫曼树) package tree;/**********

哈夫曼编码(Huffman coding)的那些事,(编码技术介绍和程序实现)

前言 哈夫曼编码(Huffman coding)是一种可变长的前缀码.哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为<A Method for the Construction of Minimum-Redundancy Codes>的文章.编码这种编码的过程叫做哈夫曼编码,它是一种普遍的熵编码技术,包括用于无损数据压缩领域.由于哈夫曼编码的运用广泛,本文将简要介绍: 哈夫曼编码的编码(不包含解码)原理 代码(java)实现过程 一

哈夫曼(Huffman)树与哈夫曼编码

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289610.html 哈夫曼树又称最优二叉树,是一种带权路径长最短的树.树的路径长度是从树根到每一个叶子之间的路径长度之和.节点的带树路径长度为从该节点到树根之间的路径长度与该节点权(比如字符在某串中的使用频率)的乘积. 比如有一串字符串如

HDU 1053 Entropy(哈夫曼编码 贪心+优先队列)

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1053 Entropy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7233    Accepted Submission(s): 3047 Problem Description An entropy encoder is a data

20172327-哈夫曼编码测试

20172327-哈夫曼编码测试 哈夫曼编码与哈夫曼树 哈夫曼编码步骤 用Java实现哈夫曼编码 实验结果截图 码云链接 感悟 参考资料 原文地址:https://www.cnblogs.com/mrf1209/p/10111365.html

20182327 2019-2020 《程序设计与数据结构》哈夫曼编码测试报告

20182327 2019-2020 <程序设计与数据结构>哈夫曼编码测试报告 课程:<程序设计与数据结构> 班级: 1823 姓名:赵天昊 学号:20182327 实验教师:王志强 实验日期:2019年11月17日 必修/选修: 必修 教材中的哈夫曼树 1.在计算机数据处理中,哈夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字

基于python的二元霍夫曼编码译码详细设计

一.设计题目 对一幅BMP格式的灰度图像(个人证件照片)进行二元霍夫曼编码和译码 二.算法设计 (1)二元霍夫曼编码: ①:图像灰度处理: 利用python的PIL自带的灰度图像转换函数,首先将彩色图片转为灰度的bmp图像,此时每个像素点可以用单个像素点来表示. ②:二元霍夫曼编码: 程序流程图: 详细设计: 统计像素点频率,首先通过python自带的PIL库的图像像素点读取函数read()获取灰度图像的所有像素点,通过循环遍历每个像素点,将每个出现的像素点值以及其次数以键值对的形式放入到pyt

霍夫曼编码求节省空间

霍夫曼编码将频繁出现的字符采用短编码,出现频率较低的字符采用长编码.具体的操作过程为:i)以每个字符的出现频率作为关键字构建最小优先级队列:ii)取出关键字最小的两个结点生成子树,根节点的关键字为孩子节点关键字之和,并将根节点插入到最小优先级队列中,直至得到一棵最优编码树. 霍夫曼编码方案是基于______策略的.用该方案对包含a到f6个字符的文件进行编码,文件包含100000个字符,每个字符的出现频率(用百分比表示)如表1-3所示,则与固定长度编码相比,该编码方案节省了______存储空间.