哈夫曼树

概念

哈夫曼编码应用广泛,如JPEG中就应用了哈夫曼编码。

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL= (W1*L1+W2*L2+W3*L3+…+Wn*Ln),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明哈夫曼树的WPL是最小的。

哈夫曼编码步骤:
一、对给定的n个权值{W1,W2,W3,…,Wi,…,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,…,Ti,…,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算 法,一般还要求以Ti的权值Wi的升序排列。)
二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止。

java实现

package com.cn;

import java.util.ArrayList;
import java.util.List;

//定义树的节点
class TreeNode{
    int weight; //权重
    TreeNode leftNode;//左子树
    TreeNode rightNode;//右子树
    TreeNode parentNode;//根节点

    //构造函数
    public TreeNode(){}

    public TreeNode(int weight){
        this.weight = weight;
    }

    @Override
    public String toString(){
        return this.weight + "";
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

public class HuffmanTree {
    public static void main(String[] args) {
        int[] a = new int[]{2,21,12,24,12};
        List list = new ArrayList();
        HuffmanTree ht = new HuffmanTree();
        ht.SortWeight(a, list);

        TreeNode root = ht.CreatTree(list);
        ht.print(root);
    }

    //首先将数组中的每个数,生成一课单独的树,然后将所有的这些树添加进list集合中,并对其进行排序
    public void SortWeight(int[] a,List list){

        for(int i = 0; i < a.length; i++){
            TreeNode node = new TreeNode(a[i]);
            list.add(node);
        }

        //排序
        list.sort((o1,o2)->((TreeNode)o1).getWeight() - ((TreeNode)o2).getWeight());

        System.out.println(list);
    }
    //构建哈夫曼树
    public TreeNode CreatTree(List list){

        if(list.size() <= 1){
            return null;
        }

        //集合中的元素个数必须大于1才可以
//      while(list.size() > 1){
            //获取集合中权值最小的两个节点,并将其从集合中删除
            TreeNode node1 = (TreeNode)list.remove(0);
            TreeNode node2 = (TreeNode)list.remove(0);
            //根据两个小节点,创建他们的父节点
            TreeNode node3 = new TreeNode();
            node3.weight = node1.weight + node2.weight;
            //建立三个节点之间的关系
            node3.leftNode = node1;
            node3.rightNode = node2;
            node1.parentNode = node3;
            node2.parentNode = node3;
            //把父节点添加进集合,并重新排序
            list.add(node3);
            list.sort((o1,o2)->((TreeNode)o1).getWeight() - ((TreeNode)o2).getWeight());

//      }

        CreatTree(list);

        TreeNode root = (TreeNode)list.get(0);

        return root;
    }
    //前序遍历哈夫曼树
    public void print(TreeNode root){

        if(root == null){
            return;
        }

        System.out.print(root.weight + " ");
        print(root.leftNode);
        print(root.rightNode);
    }

}
/**
输出结果:
[2, 12, 12, 21, 24]
71 26 12 14 2 12 45 21 24 
*/

资料收集自:
哈夫曼树http://blog.csdn.net/shuangde800/article/details/7341289
java实现哈夫曼树http://2509477698.iteye.com/blog/1683658

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值