哈夫曼树的创建

本文介绍了哈夫曼树的概念,它是如何通过给定一组数值构建,以及如何计算带权路径长度(WPL)。步骤详细讲解了从排序到递归合并的过程,并附有代码实现,展示了前序遍历。重点在于如何利用Collections.sort方法创建最优二叉树。
摘要由CSDN通过智能技术生成

什么是哈夫曼树?

给定n个值作为n个叶子节点,构造出一个二叉树,若该数的wpl(该树的带权路径长度)最小,那么这样的二叉树被称为最优二叉树,同时也被称为哈夫曼树。
那么怎么计算wpl?
在这里插入图片描述
wpl=5❌2+7❌2+2❌2+13❌2= 54

结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为 WPL(weighted path length) ,权值越大的结点离根结点越近的二叉树才是最优二叉树。

创建哈夫曼树步骤:

题:给定1个数组,构建1个哈夫曼树

1.从小到大进行排序,将每一个数都当做一个节点,每个节点都是1个二叉树。
2.取出根节点权值最小的两棵二叉树。
3.再创建1个新的二叉树,该二叉树的根节点的权值是前面两棵二叉树的权值之和。
4.将新的二叉树代入进行重新排序,重复前4个步骤,直到数列中的所有数全被处理。

代码实现:

代码中的前序遍历代码:
链接: 前序遍历和数的创建

注意:
该代码排序用的是Collections中的sort方法,用该方法需要实现Comparable接口,并重写里面的CompareTo方法。

public class HeFuManTree {
    public static void main(String[] args) {
        int arr[] = {13,7,8,3,29,6,1};
        Node haFuManTree = createHaFuManTree(arr);
        preOrder(haFuManTree);
    }
    public static Node createHaFuManTree(int[] arr){
            //1.先遍历数组
            //2.将arr中的每个元素构成1个Node
            //3.将Node放入ArryList中
            List<Node> nodes = new ArrayList<Node>();
            for (int value : arr) {
                nodes.add(new Node(value));
            }
            //只要nodes中元素大于1个就不断进行该操作
            while (nodes.size() > 1){
            //先排序(从小到大),注:要想用Collections工具类中Sort方法进行排序就必须实现Comparable方法
            Collections.sort(nodes);
            //取出权值最小的1个数,当从小到大排完后,最小的就是第一个数
            //用它来充当左子节点
            Node leftNode = nodes.get(0);
            //取出权值第二小的数,当从小到大排完后,最小的就是第二个数
            //用它来充当右子节点
            Node rightNode = nodes.get(1);
            //构建1个新的二叉树
            //新的二叉树的根节点(root)就是前两个左右子节点的值和
            Node parentNode = new Node(leftNode.value + rightNode.value);
            //将新的二叉树的左右子节点也进行赋值操作
            parentNode.left = leftNode;
            parentNode.right = rightNode;
            //从ArrayList中删除原本的二叉树
            nodes.remove(leftNode);
            nodes.remove(rightNode);
            //将新的二叉树加入nodes中
            nodes.add(parentNode);
        }
        return nodes.get(0);
    }
    //传入头节点(root)
    public static void preOrder(Node root){
       if(root != null){
           root.preOrder();
       }else {
           System.out.println("为null");
       }
    }
}
class Node implements Comparable<Node>{
    int value; //该节点的值
    Node left; //该节点的左子节点
    Node right; // 该节点的右子节点
    //创建1个构造器
    public Node(int value){
        this.value = value;
    }
    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

    @Override
    public int compareTo(Node o) {
        //表示从小到大进行排序
        return this.value - o.value;
    }
    //编写1个前序遍历的方法
    public void preOrder(){
        //先输出头节点(root)
        System.out.println(this);
        //如果左子树不为null,就递归左子树
        if(this.left != null){
            this.left.preOrder();
        }
        if(this.right != null){
            this.right.preOrder();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱敲键盘的程序源

你的激励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值