zoukankan      html  css  js  c++  java
  • 赫夫曼树

    基本介绍

    • 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,这样的二叉树为最优二叉树,也称为赫夫曼树
    • 赫夫曼树是带权路径长度最短的数,权值较大的节点离根较近

    赫夫曼树几个重要概念

    • 1.路径和路径长度:在一棵树中,从一个节点往下可以达到的孩子或孙子节点之间的通路,称为路径.通路中分支的数目称为路径长度.若规定根节点的层数为1,则从根节点到第L层节点的路径长度为L-1
      1. 节点的权及带权路径长度:若将树中节点赋给一个有着某种含义的数值,则这个数值称为该节点的权.节点的带权路径长度为:从根节点到该节点之间的路径长度与该节点的权的乘积.
      1. 树的带权路径长度:树的带权路径长度规定为所有叶子节点的带权路径长度之和,记为WPL,权值越大的节点离根节点越近
    • WPL最小的就是赫夫曼树

    赫夫曼树创建思路图解

    给你一个数列{13, 7, 8, 3, 29, 6, 1},要求转成一棵赫夫曼树.

    构成赫夫曼树的步骤:

    • 从小到大进行排序,将每一个数据都是一个节点,每个节点可以看成是一棵简单的二叉树
    • 取出根节点权值最小的两颗二叉树
    • 组成一棵新的二叉树,该新的二叉树的根节点的权值是前面两颗二叉树根节点权值的和
    • 再将这棵新的二叉树,以根节点的权值大小再次排序,不断重复 上述步骤,知道数列中所有数据都被处理,就得到一棵赫夫曼树

    代码实现

    public class HuffumanTree {
        public static void main(String[] args) {
            int[] arr = {13, 7, 8, 3, 29, 6, 1};
            HuffumanNode root = createHuffumanTree(arr);
            //进行前序遍历,检测是否构建成功
            preOrder(root);
    
        }
        //前序遍历
        public static void preOrder(HuffumanNode root){
            if (root == null){
                System.out.println("赫夫曼树为空");
            }else {
                root.preOrder();
            }
        }
        //构建赫夫曼树
        private static HuffumanNode createHuffumanTree(int[] arr) {
            //1.遍历arr,将其放入list中,方便排序
            List<HuffumanNode> nodes = new ArrayList<>();
            for (int item:arr) {
                nodes.add(new HuffumanNode(item));
            }
            //集合中只有一个元素时,就表示赫夫曼树构建成功了,这个元素就是根节点
            while (nodes.size()>1){
                //排序
                Collections.sort(nodes);
                //取出集合前两个元素,即最小的两个元素
                HuffumanNode leftNode = nodes.get(0);
                HuffumanNode rightNode = nodes.get(1);
                //构成树
                HuffumanNode parent = new HuffumanNode(leftNode.val + rightNode.val);
                parent.left = leftNode;
                parent.right = rightNode;
                //从列表中删除取出的元素,并将paret添加到集合中
                nodes.remove(leftNode);
                nodes.remove(rightNode);
                nodes.add(parent);
            }
            return nodes.get(0);
        }
    }
    
    //因为需要进行排序,所以实现 Comparable 接口
    class HuffumanNode implements Comparable<HuffumanNode>{
        int val; //值
        HuffumanNode left;  //左节点
        HuffumanNode right;  //右节点
    
        public HuffumanNode(int val) {
            this.val = val;
        }
    
    
        @Override
        public String toString() {
            return "HuffumanNode{" +
                    "val=" + val +
                    '}';
        }
    
        @Override
        public int compareTo(HuffumanNode o) {
            //从小到大
            return this.val-o.val;
        }
    
        //前序遍历
        public void preOrder(){
            System.out.println(this);
            if (this.left!=null){
                this.left.preOrder();
            }
            if (this.right!=null){
                this.right.preOrder();
            }
        }
    }
    
    
  • 相关阅读:
    "无法在证书存储区中找到清单签名证书"的解决办法
    Windows消息ID说明
    ToolBar来的是什么事. (ToolBar 难见的Bug)
    SQL Tips 收集常用的SQL
    郁闷的内存泄露,增加TmfEditFormCmptMgr.OnDstMainSetFieldData惹的祸
    FormDestroy和Destroy中选其一个使用.
    一步步教你优化Delphi字串查找(转载)
    利用SQL建立数据库对象
    数据字典ChangeName引发的问题.
    测试Live Writer
  • 原文地址:https://www.cnblogs.com/liuzhidao/p/13886274.html
Copyright © 2011-2022 走看看