zoukankan      html  css  js  c++  java
  • 数据结构—哈夫曼树(Java)

    数据结构—哈夫曼树(Java)

    博客说明

    文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!

    说明

    • 给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)

    • 赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

    • 树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL(weighted path length) ,权值越大的结点离根结点越近的二叉树才是最优二叉树

    • WPL最小的就是赫夫曼树

    思路

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

    代码

    package cn.guizimo.huffmantree;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    /**
     * @author guizimo
     * @date 2020/8/8 11:01 上午
     */
    public class HuffmanTree {
        public static void main(String[] args) {
            int arr[] = {13, 7, 8, 3, 29, 6, 1};
            Node root = createHuffmanTree(arr);
            System.out.println("哈夫曼树前序遍历:");
            preOrder(root);
    
        }
    
    		//前序遍历
        public static void preOrder(Node root){
            if(root != null){
                root.preOrder();
            }else {
                System.out.println("空树");
            }
        }
    
        public static Node createHuffmanTree(int[] arr) {
            List<Node> nodes = new ArrayList<>();
            for (int value : arr) {
                nodes.add(new Node(value));
            }
            while (nodes.size() > 1) {
                //使用集合排序
                Collections.sort(nodes);
    
    						//获取左右子节点
                Node leftNode = nodes.get(0);
                Node rightNode = nodes.get(1);
    						
    						//构建子树
                Node parent = new Node(leftNode.value + rightNode.value);
                parent.left = leftNode;
                parent.right = rightNode;
    
    						//删除已使用的子节点
                nodes.remove(leftNode);
                nodes.remove(rightNode);
                
                //将新的子树的根节点放入集合
                nodes.add(parent);
            }
            //返回根节点
            return nodes.get(0);
        }
    }
    
    //节点
    class Node implements Comparable<Node> {
        int value;
        Node left;
        Node right;
    
    		//前序遍历
        public void preOrder(){
            System.out.println(this);
            if(this.left != null){
                this.left.preOrder();
            }
            if(this.right != null){
                this.right.preOrder();
            }
        }
    
        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;
        }
    }
    

    测试

    image-20200808112700752

    感谢

    尚硅谷

    以及勤劳的自己

    关注公众号: 归子莫,获取更多的资料,还有更长的学习计划

  • 相关阅读:
    对拍程序的写法
    单调队列模板
    [bzoj1455]罗马游戏
    KMP模板
    [bzoj3071]N皇后
    [bzoj1854][SCOI2010]游戏
    Manacher算法详解
    [bzoj2084][POI2010]Antisymmetry
    Python_sklearn机器学习库学习笔记(一)_一元回归
    C++STL学习笔记_(1)string知识
  • 原文地址:https://www.cnblogs.com/guizimo/p/13456945.html
Copyright © 2011-2022 走看看