> 文档中心 > 赫夫曼树的介绍和构造

赫夫曼树的介绍和构造


赫夫曼树

基本介绍

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

赫夫曼树几个重要概念和举例说明

  1. 路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为 1,则从根结点到第 L 层结点的路径长度为 L-1
  2. 结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积
  3. 树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL(weighted path length) ,权值越大的结点离根结点越近的二叉树才是最优二叉树。
  4. WPL 最小的就是赫夫曼树
    在这里插入图片描述

赫夫曼树创建思路图解

给你一个数列 {13, 7, 8, 3, 29, 6, 1},要求转成一颗赫夫曼树.
思路分析(示意图): {13, 7, 8, 3, 29, 6, 1}
构成赫夫曼树的步骤:

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

代码实现

package com.iflytek.huffmantree;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class HuffmanTree {    public static void main(String[] args) { int[] arr = {13, 7, 8, 3, 29, 6, 1}; Node root = createHuffmanTree(arr); //测试一把 preOrder(root);    }    //编写一个前序遍历的方法    public static void preOrder(Node root) { if (root != null) {     root.preOrder(); } else {     System.out.println("是空树,不能遍历~~"); }    }    /**     * 创建赫夫曼树的方法     *     * @param arr 需要创建成哈夫曼树的数组     * @return 创建好后的赫夫曼树的 root 结点     */    public static Node createHuffmanTree(int[] arr) { // 第一步为了操作方便 // 1. 遍历 arr 数组 // / 2. 将 arr 的每个元素构成成一个Node // 3. 将Node 放入到ArrayList 中 List<Node> nodes = new ArrayList<>(); for (int value : arr) {     nodes.add(new Node(value)); } //我们处理的过程是一个循环的过程 while (nodes.size() > 1) {     //排序 从小到大     Collections.sort(nodes);     //取出根节点权值最小的两颗二叉树     // (1) 取出权值最小的结点(二叉树)     Node leftNode = nodes.get(0);     //(2) 取出权值第二小的结点(二叉树)     Node rightNode = nodes.get(1);     //(3)构建一颗新的二叉树     Node parent = new Node(leftNode.value + rightNode.value);     parent.left = leftNode;     parent.right = rightNode;     //(4)从ArrayList 删除处理过的二叉树     nodes.remove(leftNode);     nodes.remove(rightNode);     nodes.add(parent); } //返回哈夫曼树的 root 结点 return nodes.get(0);    }}// 创建结点类// 为了让Node 对象持续排序 Collections 集合排序// 让Node 实现 Comparable 接口class Node implements Comparable<Node> {    int value;// 结点权值    Node left;// 指向左子结点    Node right;// 指向右子结点    public Node(int value) { this.value = value;    }    @Override    public String toString() { return "Node{" +  "value=" + value +  '}';    }    @Override    public int compareTo(Node node) { // 表示从小到大排序 return this.value - node.value;    }    //写一个前序遍历    public void preOrder() { System.out.println(this); if (this.left != null) {     this.left.preOrder(); } if (this.right != null) {     this.right.preOrder(); }    }}