java实现哈弗曼编码

根据输入的各个叶节点的权值,构建一棵最优树,根据最小带全路径,确定由0,1组成的哈弗曼编码。

首先在一个封装类TNode中构建一棵树的元素,比如权值,左节点,右节点,同时在TNode类中构建了哈弗曼编码值,以及判断节点是否为叶子节点

package 霍夫曼编码;
/**
 *
 * @author luckid
 * @version 2014_10_11
 *
 */

/**
 * 定义Huffman编码的节点
 */

public class TNode {
    /**
     *
     * @param weight
     * @param left
     * @param right
     */

    /*protected*/ int weight;                                        //权值
    TNode left=null;                                            //左节点
    TNode right=null;                                            //右节点
    String code=null;                                            //霍夫曼编码
/**
 *  构造一个赫夫曼编码节点的实例。设定左右子树和权值
 */
    public TNode(int weight,TNode left,TNode right){
        this.weight=weight;
        this.left=left;
        this.right=right;

    }

    /**
     *
     * @author 刘雁冰as
     * @date 2015-02-08 1943
     *
     */
    public TNode(int weight){
        this.weight=weight;
    }

    /**
     * 判断本节点是否为叶子节点
     * @return boolean 为叶子节点则返回true
     */
    public boolean isLeaf(){
        return (left==null&&right==null);
    }

    /**
     * 返回本节点的权值
     * @return nt 本节点的权值
     */
    public int getWeight(){
        return weight;
    }

    /**
     * 返回本节点的左孩子节点
     * @return TNode 左孩子节点
     */
    public TNode getLeft(){
        return left;
    }

    /**
     * 返回本节点的右孩子节点
     * @return TNode 右孩子节点
     */
    public TNode getRight(){
        return right;
    }

    /**
     * 设置节点的赫夫曼编码
     * @param str String 被设置的赫夫曼编码
     */
    public void setCode(String str){
        code=str;
    }

    /**
     * 得到节点的赫夫曼编码
     * @return String 被设置的赫夫曼编码
     */
    public String getCode(){
        return code;
    }

}

  

在Tree类中,构建一棵最优树。首先从键盘读入权值,在这里用1,3,5,7作为测试数据,将读入的测试数据放在一个数组链表中。接着使用迭代器求出最小的叶子节点,然后递归构建一棵最优树,在建构最优树的时候,一次递归需要找出权值最小的叶子节点以及权值次小的叶子节点,两个节点构成一棵子最优树。循序渐进继续递归,直到数组链表中只剩下一个数据,作为整棵最优树的根节点。

测试数据构成的最优子树应该如下:

    /**
     * 定义最优二叉树
     */
    /*protected*/ TNode root;                                                                            //二叉树根节点
    /*protected*/ List<Integer>leafList=new ArrayList<Integer>();            //存储叶子节点的权值
    /*protected*/ List<TNode>tempList=new LinkedList<TNode>();            //临时队列,用于存放待组合的节点
    /*protected*/TNode[]leafArr=null;                                                            //存放带权节点

    /**
     * 键盘读取各个权值
     */
    public void getLeafWeight(){
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入各个叶节点的权值,按0为结束:");
        while(sc.hasNextInt()){
            int i=sc.nextInt();
            if(i==0)
                break;
            leafList.add(new Integer(i));
        }
        sc=null;
        return ;
    }

    /**
     * 找出临时队列中权值最小的节点从队列中移出并返回
     * @return TNode 权值最小的节点
     */
    public TNode min(){
        Iterator<TNode>iter=tempList.iterator();
        TNode minNode=iter.next();
        int min=minNode.getWeight();                         //找到最小的节点
        TNode tempNode;
        while(iter.hasNext()){
            tempNode=iter.next();
            if(tempNode.getWeight()<min){
                min=tempNode.getWeight();
                minNode=tempNode;
            }
        }
        tempList.remove(minNode);                              //最小的节点移出临时队列
         //处理垃圾
        iter=null;
        tempNode=null;
        return minNode;
    }

    /**
     * 根据权值创建叶子节点并加入临时队列
     */
    public void makeLeafNode(){
        leafArr=new TNode[leafList.size()];
        for(int i=0;i<leafList.size();i++){
            TNode node=new TNode(leafList.get(i).intValue());
            leafArr[i]=node;
            tempList.add(node);
        }
    }

    /**
     * 根据权值构造最优的二叉树
     */
    public void makeBestTree(){
        makeLeafNode();                                                    //根据权值创建叶子节点并加入临时队列
        TNode minNode1=null;
        TNode minNode2=null;
        TNode node=null;
        while(tempList.size()!=1){                                         //构造最优树
            minNode1=min();
            minNode2=min();
            node=new TNode(minNode1.getWeight()+minNode2.getWeight(),minNode1,minNode2);
            tempList.add(node);
        }
        root=node;
    }

构建好了最优树,就可以用HuffmanCode类拓展最优二叉树实现哈弗曼编码。在HuffmanCode类中递归调用huff()方法创建哈弗曼树结构,并且为每个叶子节点赋值,其中左子树赋值0,右子树赋值1

package 霍夫曼编码;

/**
 *
 * @author 刘雁冰as
 * @date 2015-02-08 1943
 *
 */

/**
 * 拓展最优二叉树实现Huffman编码
 * 赫夫曼编码类
 */
public class HuffmanCode extends Tree{
    public HuffmanCode(){
        init();
    }

    /**
     * 初始化节点值并构造最优二叉树
     */
    public void init(){
        super.getLeafWeight();
        super.makeBestTree();
    }

    /**
     * 生成赫夫曼编码的递归函数
     *
     * @param t TNode 当前遍历节点
     * @param s String 目前遍历至此的赫夫曼编码
     */
    /*protected*/public  void huff(TNode t,String s){
        if(t.isLeaf()){
            t.setCode(s);
        }
        else{
            huff(t.left,s+"0");
            huff(t.right,s+"1");
        }
    }

    /**
     * 生成赫夫曼编码的外部调用函数
     */
    public void makeHuffmanCode(){
        huff(root,"");
    }

    /**
     * 查看所有的赫夫曼编码值
     */
    public void viewHuffmanCode(){
        for(int i=0;i<leafArr.length;i++){
            System.out.println(leafArr[i].weight+":"+leafArr[i].getCode());
        }
    }

}

测试类:

package 霍夫曼编码;

public class Application {

    /**
     *
     * @author 刘雁冰as
     * @date 2015-02-08 1943
     *
     */
    public static void main(String args[]){
        // TODO Auto-generated method stub
        HuffmanCode hu=new HuffmanCode();
        hu.makeHuffmanCode();
        hu.viewHuffmanCode();
    }

}

测试结果如下:

时间: 2024-10-11 17:50:53

java实现哈弗曼编码的相关文章

java实现哈弗曼树

O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如用于压缩,用于密码学等.今天一起来看看哈弗曼树到底是什么东东. 概念 当然,套路之一,首先我们要了解一些基本概念. 1.              路径长度:从树中的一个结点到另一个结点之间的分支构成这两个结点的路径,路径上的分支数目称为路径长度. 2.              树的路径长度:从树

用哈弗曼编码实现文件压缩和解压

放假了把这个改一下,发现确实用单字节压缩的压缩率要高一些,暂时没去管为什么,不过放假静下心来写的话确实效率高很多. 新版详见:http://blog.csdn.net/tookkke/article/details/50575103 今天脑洞大开突然想写一下,明明都要考试了,唉,怎么就管不住这手啊  总之呢,就是根据每种编码的出现频率把等长的编码换成变长的,据说理论上压缩比率是比较高的,可是为什么经检验我这个大部分时候压缩出来的比源文件还大呢? 哈弗曼编码的时候要先做一颗字典树,查找的时候就按照

哈弗曼编码和译码.cpp

<span style="color:#6600cc;">#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct{ char a;//记录对应字符 int weight;//权值 int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char * *HuffmanCode;//动态分配数组存储哈夫

uva 10954 Add All(哈弗曼编码)

这道题我一开始想错了,这么简单的题都wa了两发...我往贪心上面想了,每次都找一个最小的数相加,结果就是 排序后直接往后加,还在那纳闷为何出错...其实这道题是哈弗曼编码问题,简直是模板题目,就是每次找两个最 小的结点求和后把他们的和放到节点中去,把这两个点删除...用的multiset,其实和set容器差不多,就是可 以存放重复的元素... 代码: #include<iostream> #include<cstdio> #include<cstdlib> #inclu

数据结构实验2(设计哈弗曼编码和译码系统)

设计一个哈弗曼编码和译码系统, 要求如下: B--建树:读入字符集和各字符频度,建立哈夫曼树. T--遍历:先序和中序遍历二叉树. E--生成编码:根据已建成的哈夫曼树,产生各个字符的哈夫曼编码. C--编码:输入由字符集中字符组成的任意字符串,利用已生成的哈夫曼编码进行编码,显示编码结果,并将输入的字符串及其编码结果分别保存在磁盘文件textfile.txt和codefile.txt中. D--译码:读入codefile.txt,利用已建成的哈夫曼树进行译码,并将译码结果存入磁盘文件resul

利用哈弗曼编码进行压缩

// sZipDemo.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "HuffmanTree.cpp" #include "sZip.h" #include <fstream> #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { char str1[100

哈弗曼编码译码系统

/**********************************************************************                                        * 学校:黄淮学院                                                         * 院系:信息工程学院                                                     * 年级专业:网络

哈弗曼编码解码

#lang scheme ( define nil '() ) ( define ( make-leaf symbol weight ) ( list 'leaf symbol weight ) ) ( define ( leaf? obj ) ( eq? ( car obj ) 'leaf ) ) ( define ( symbol-leaf x ) ( cadr x ) ) ( define ( weight-leaf x ) ( caddr x ) ) ( define ( make-co

【算法设计与分析】8、哈弗曼编码,贪心算法实现

写这个玩意,我也是深深地感觉到自己数据结构的薄弱,可笑的是我一直以为学的还可以,结果一个堆结构就干了我半个月,才懂个大概= =,我也是醉了 BinaryTree.h二叉树的实现 /** * 书本:<算法分析与设计> * 功能:这个头文件是为了实现二叉树 * 文件:BinaryTree.h * 时间:2014年12月15日18:35:51 * 作者:cutter_point */ // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |