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

原理:哈夫曼编码是根据将已给出的权值作为叶子结点,生成一颗哈夫曼树,然后使得权重最小。

首先生成已给权重的所有的叶子结点,然后取所有节点中最小和次小的结点作为左右孩子生成一个哈夫曼树,计算出父节点的权重放入给出的权重森林中,并把之前的最小和次小的结点从森林中删除,再在种种森林中找最小和次小的结点生成权重树....直到最终只剩下一个树为止。

哈夫曼树的结点用如下结点表示:

(有权重,左右孩子,父节点,然后设置一个标识符标志结点是否已经放入哈夫曼树)

package tree;
/**********哈夫曼树的节点类描述*********/
public class HuffmanNode {
private int weight;//权重
private int flag;//是否加入到huffman树中
private HuffmanNode parent,lchild,rchild;//树种的结点之间的关系
public HuffmanNode(){//构造空结点
    this(0);
}
public HuffmanNode(int weight){//构造只具有权值的空结点
    this.weight=weight;
    flag=0;
    parent=lchild=rchild=null;
}
public void setweight(int weight){
    this.weight=weight;
}
public int getweight(){
    return weight;
}
public void setflag(int flag){
    this.flag=flag;
}
public int getflag(){
    return flag;
}
public void setparent(HuffmanNode parent){
    this.parent=parent;
}
public HuffmanNode getparent(){
    return parent;
}
public void setlchild(HuffmanNode lchild){
    this.lchild=lchild;
}
public HuffmanNode getlchild(){
    return lchild;
}
public void setrchild(HuffmanNode rchild){
    this.rchild=rchild;
}
public HuffmanNode getrchild(){
    return rchild;
}
}

哈夫曼树的构造:

用给出的权重数组构造哈夫曼树,首先要先给每个权重生成哈夫曼结点代用(标志为放入哈夫曼树 falg=0);

计算得出最终哈夫曼树中会有多少个结点,由叶子结点为n,则总结点为2*n-1个;

所以要其次接入n-1个结点(下标为:n--m-1);首先选n个中的二最小和次小结点比较(设置一个比较函数对HN中的所有节点遍历,找到之后设置flag=1,然后再次寻找HN中的最小结点),最终构成整个哈夫曼树

然后由叶子结点开始读出哈夫曼编码:

package tree;
public class HuffmanTree {
public int[][] huffmanCoding(int[] w){
    int n=w.length;
    int m=2*n-1;
    HuffmanNode[] HN=new HuffmanNode[m];//生成一个元素为哈夫曼树结点的数组
    int i;
    for(i=0;i<n;i++){
        HN[i]=new HuffmanNode(w[i]);//生成哈夫曼树的叶子结点
    }
    for(i=n;i<m;i++){
        HuffmanNode min1=selectMin(HN,i-1);
        min1.setflag(1);
        HuffmanNode min2=selectMin(HN,i-1);//上面找到的那个flag已标志为1,所以不会再次寻找
        min2.setflag(1);//找到所有节点中权重最小的结点加入到哈夫曼树中
        HN[i]=new HuffmanNode();
        min1.setparent(HN[i]);
        min2.setparent(HN[i]);
        HN[i].setlchild(min1);
        HN[i].setrchild(min2);
        HN[i].setweight(min1.getweight()+min2.getweight());//修改两个结点的父节点,及权重
    }
    int[][] HuffCode=new int[n][n];//分配n个字符编码存储空间
    for(int j=0;j<n;j++){//数组
        int start=n-1;

//从后开始 对HuffCode数组每个结点的下标由后向前填充,保证编码的前缀相同00... huffCode[0][6]=1 huffCode[0][5]=0

//则huffCode 为0000 0001即小标为1的一个哈夫曼结点的哈夫曼变慢
            for(HuffmanNode c=HN[j],p=c.getparent();p!=null;c=p,p=p.getparent()){
                if(p.getlchild().equals(c)) HuffCode[j][start--]=0;
                else HuffCode[j][start--]=1;
            }//对同一个结点的路径做遍历
            HuffCode[j][start--]=-1;//对剩余的路径为填充-1
    }//对n个叶子结点的路径做遍历
    return HuffCode;//返回哈夫曼编码数组
}
private HuffmanNode selectMin(HuffmanNode[] HN,int end){
    HuffmanNode min=HN[end];
    for(int i=0;i<=end;i++){
        HuffmanNode h=HN[i];
        if(h.getflag()==0&&h.getweight()<min.getweight())
            min=h;
    }
    return min;
}

public static void main(String[] args){
    int[] w={23,11,5,3,29,14,7,8};
    HuffmanTree t=new HuffmanTree();
    int[][] HN=t.huffmanCoding(w);
    System.out.println("哈弗满编码为:");
    for(int i=0;i<HN.length;i++){//n个叶子结点
        System.out.print(w[i]+": ");
        for(int j=0;j<HN[i].length;j++){//每个叶子结点对应一个结点的n个编码位置做遍历
            if(HN[i][j]==-1){//值输出有路径的编码位(n位中的后几位)
                for(int k=j+1;k<HN[i].length;k++)
                    System.out.print(HN[i][k]);
                break;
            }
        }
        System.out.println();
        
    }
}
}

结果:

哈弗满编码为:
23: 01
11: 001
5: 11111
3: 11110
29: 10
14: 110
7: 1110
8: 000

哈夫曼树为:

时间: 2024-10-23 22:07:04

数据结构(java语言描述)哈夫曼编码的相关文章

C语言之霍夫曼编码学习

?1,霍夫曼编码描述哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩. 在计算机信息处理中,"哈夫曼编码"是一种一致性编码法(又称"熵编码法"),用于数据的无损耗压缩.这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码.这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目

数据结构(java语言描述)顺序栈的使用(两个大数相加)

利用http://www.cnblogs.com/xleer/p/5289661.html中对顺序栈以及栈的进本方法的定义,实现超过整数上限的两个数的加法计算. 算法: package stack;/********************************************************************** * @author sch ********利用栈,计算两个大数的和.大数的值超过int存储的范围******************************

数据结构(java语言描述)递归实现——汉诺塔问题

1.汉诺塔问题描述 N阶汉诺塔:假设有3个分别命名为x,y,z的三个塔座,在x上有n个盘子,直径大小不同,有小到大按标号1,2,3...n排列,要借助y将n个盘子转移到z上,期间不能让小盘子压在大盘子上.规则: 每次至移动一个盘子: 盘子可以插在x,y,z任意一个塔座上: 任何时候都不能将大盘压在小盘上. 2.解题思路 当n=1时,直接把盘子由x——>z; 当n>1时,需利用y,首先将(n-1)个盘子由x——>y,把第n个实现x——>z,然后把问题转换为实现(n-1)个盘子由y——

数据结构(java语言描述)链栈的定义

1.定义栈接口 package stack;public interface Istack {    public void clear();    public boolean isEmpty();    public int length();    public Object peek();    public void push(Object x) throws Exception;    public Object pop();} 2.定义Node结点 package stack; i

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; // 字符

哈夫曼编码

   1.问题描述 哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法.其压缩率通常在20%-90%之间.哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式.一个包含100,000个字符的文件,各字符出现频率不同,如下表所示. 有多种方式表示文件中的信息,若用0,1码表示字符的方法,即每个字符用唯一的一个0,1串表示.若采用定长编码表示,则需要3位表示一个字符,整个文件编码需要300,000位:若采用变长编码表示,给频率高的字符较短的编码:频率低的字符较长的

数据结构之---C语言实现哈夫曼树和编码

//哈夫曼树 //杨鑫 #include <stdio.h> #include <stdlib.h> typedef int ElemType; struct BTreeNode { ElemType data; struct BTreeNode* left; struct BTreeNode* right; }; //遍历哈夫曼树 void PrintBTree_int(struct BTreeNode* BT) { if (BT != NULL) { printf("

【数据结构】树与树的表示、二叉树存储结构及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树与哈夫曼编码、集合及其运算

1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找--方法一:顺序查找(时间复杂度O(n)) int SequentialSearch(St

数据结构:哈夫曼编码(php版)

演示网址:http://huffman.sinaapp.com/ 源文件下载地址:http://xiaocao.u.qiniudn.com/work/huffman-2013-12-19.zip 概述下: 哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩. 在计算机信息处理中,"哈夫曼编码"是一种一致性编码法(又称"熵编码法"),用于数据的无损耗压缩.     简单的,就是靠权值排序,然后,转码,最优保存. 实现功能: 保存译码:在服务器端保存源