• 赫夫曼树


    赫夫曼树介绍:

    • 1)给定n个权值作为n个吐子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二二叉树,也称为哈夫曼树(Huffmanree),还有的书翻译为霍夫曼树。
    • 2)赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

    赫夫曼树概念:

    1. 路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1,结点的权及带权路径长度:若将树中结点赋给一个有 着某种含义的数值,
    2. 则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积

    权:        比如给节点赋值为13,这个节点的权就是13
    带权路径:   从root节点到13号节点的路径为:3-1 = 2
    带权路径长度:13 * 2 = 26
    wpl:       所有带权路径的长度之和:13*2 + 7*2 + 8*2 + 3*2 = 62
    WPL最小的就是赫夫曼树(保证所给的节点都是叶子节点)

    如何构建赫夫曼树:

     赫夫曼树的代码实现:

    import java.util.ArrayList;
    import java.util.Collections;
    
    public class Test04_赫夫曼树 {
        public static void main(String[] args) {
            int[] arr = {13, 7, 8, 3, 29, 6, 1};
            Node root = heFuMan(arr);//返回的是二叉树的头
            qianXuOrder(root);
        }
    
        //前序遍历的方法
        public static void qianXuOrder(Node root) {
            if (root != null) {
                root.qianXuOrder();
            } else {
                System.out.println("二叉树为空,无法进行遍历!");
            }
        }
    
        /**
         * 创建赫夫曼树的方法
         *
         * @param arr : 传入要进行转换为赫夫曼树的数组
         * @return : 返回创建为赫夫曼树的root节点
         */
        public static Node heFuMan(int[] arr) {
            int count = 0;
            //1、为了操作方便,就将arr数组的每一个元素构建成一个Node
            ArrayList<Node> list = new ArrayList<>();
            for (int value : arr) {
                list.add(new Node(value));//每一个元素就成为了一个Node
            }
            //如果集合中只剩下最后一个元素的时候就跳出循环
            while (list.size() > 1) {
                //将集合进行排序
                Collections.sort(list);
                System.out.println("第"+(++count)+"次进行排序后的二叉树为:" + list);
    
                //2、取出两个最小的叶子节点,构建二叉树
                Node leftNode = list.get(0);
                Node rightNode = list.get(1);
                //构建二叉树
                Node newTree = new Node(leftNode.value + rightNode.value);
                newTree.left = leftNode;
                newTree.right = rightNode;
                //从ArrayList集合中删除已经使用过的节点
                list.remove(leftNode);
                list.remove(rightNode);
                //将新的二叉树添加到ArrayList集合中去
                list.add(newTree);
                System.out.println("新构建的二叉树:" + list);
            }
            //返回赫夫曼树的头
            return list.get(0);
        }
    }
    
    /**
     * 创建节点类Node
     * 实现Comparable接口是为了对集合进行排序操作
     */
    class Node implements Comparable<Node> {
        int value;//节点的权值
        Node left;//指向左子节点
        Node right;//指向右子节点
    
        public Node(int value) {
            this.value = value;
        }
    
        //对节点进行前序遍历的方法
        public void qianXuOrder() {
            System.out.println(this);
            if (this.left != null)//左子节点不为空就继续向左遍历
                this.left.qianXuOrder();
            if (this.right != null)
                this.right.qianXuOrder();
        }
    
        public String toString() {
            return "Node{" +
                    "value=" + value +
                    '}';
        }
    
        public int compareTo(Node node) {
            //表示从小到大进行排序
            return this.value - node.value;
        }
    }
  • 相关阅读:
    传说中的灵感
    错误: Sys.WebForms.PageRequestManagerServerErrorException: 只能在执行 Render() 的过程中调用 RegisterForEventValidation;
    只能在执行 Render() 的过程中调用 RegisterForEventValidation
    在aspx实现用户控件内Web控件的事件
    Asp.net网页上嵌入Media Player播放
    为临时表动态添加字段
    如何防止头文件被重复包含、嵌套包含
    Linux C SQLite3 编程
    Android开源项目源码下载(不断更新中)
    Android程序员必看之Android六大优势
  • 原文地址:https://www.cnblogs.com/zhangzhixi/p/13825799.html
Copyright © 2020-2023  润新知