算法系列之赫夫曼树的精解构造流程及原理分析

Posted Roninaxious

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法系列之赫夫曼树的精解构造流程及原理分析相关的知识,希望对你有一定的参考价值。

赫夫曼树又称为最优树、最优二叉树

赫夫曼树百度百科https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769?fromtitle=%E8%B5%AB%E5%A4%AB%E6%9B%BC%E6%A0%91&fromid=7406794&fr=aladdin

📚赫夫曼树相关的名词

(1).路径

📑一个结点到另外一个结点的通路成为路径

(2).路径长度

📑通路中分支的数目称为路径长度,若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。

(3).结点的权

📑若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权

(4).结点的带权路径长度

📑从根结点到该结点之间的路径长度与该结点的权的乘积。

(5).树的带权路径长度

📑树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。

赫夫曼树的特点

在构建哈弗曼树时,要使树的带权路径长度最小,只需要遵循一个原则,那就是:权重越大的结点离树根越近。在图 1中,因为结点 a 的权值最大,所以理应直接作为根结点的孩子结点。

📚赫夫曼树的构建流程分析

以该结点集合[5,29,7,8,14,23,3,11]为例

1.讲每个结点存放到集合当中

2.对该集合进行排序(按照权值大小)

3.从集合中取出两个结点,创建一个新的结点作为它们的父节点,父节点的权值等于两个子节点的之和。


4.讲父节点加入到集合当中,从集合中移除这两个子结点

5.周而复始的执行1~4步即可,直到list.size <= 1;此时集合中剩下最后一个结点,而这个结点就是哈夫曼树的根节点(100)


📚源代码

public class HuffmanTree {
	//测试
    public static void main(String[] args) {
        int[] arr = {13, 7, 8, 3, 29, 6, 1};
        HuffNode root = buildHuffmanTree(arr);
        preErgodic(root);
    }
	/**
	 *1.首先遍历数组,将权值依次封装到HuffNode对象中,并加入到List集合
	 *2.由于实现类Comparable接口,所以使用Collections.sort进行集合排序
	 *3.分别从集合中取出两个结点,然后创建一个新的父节点(父节点的权值即为两个子节点的权值之和,将left和right指针分别指向两个子节点。
	 *4.将父节点加入到list集合中
	 *5.循环1-4步,直到size == 1 ,也就是集合中只剩下哈夫曼树的根节点
	 */
    private static HuffNode buildHuffmanTree(int[] arr) {
        List<HuffNode> list = new ArrayList<>();
        for (int value : arr) {
            list.add(new HuffNode(value));
        }

        while (list.size() > 1) {
            Collections.sort(list);
            HuffNode leftNode = list.remove(0);
            HuffNode rightNode = list.remove(0);
            HuffNode root = new HuffNode(leftNode.value + rightNode.value);
            root.left = leftNode;
            root.right = rightNode;
            list.add(root);
        }
        return list.remove(0);
    }
	//对构建好的哈夫曼树进行先序遍历
    private static void preErgodic(HuffNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.value + "->");
        preErgodic(root.left);
        preErgodic(root.right);
    }

}
/**
*集成Comparable接口,实现其中的compareTo方法;方便后序使用Collections.sort进行排序
*/
class HuffNode implements Comparable<HuffNode> {
    public int value;	//结点的权值
    public HuffNode left;//结点的左指针
    public HuffNode right;	//结点的右指针

    public HuffNode(int value) {
        this.value = value;
    }
//this.value-o.value表示进行升序排序
    @Override
    public int compareTo(HuffNode o) {
        return this.value - o.value;
    }
}

以上是关于算法系列之赫夫曼树的精解构造流程及原理分析的主要内容,如果未能解决你的问题,请参考以下文章

算法系列之赫夫曼编码实战一数据压缩数据解压

fasttext的原理剖析

018-Huffman树-贪心-《算法设计技巧与分析》M.H.A学习笔记

深入浅出SpringCloud原理及实战「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的Command创建和执行实现原理分析

Java- 哈夫曼(Huffman)压缩算法

哈夫曼码编码器的软件实现(Matlab编程)