数据结构——霍夫曼树及题目场景应用

什么是霍夫曼树

霍夫曼树是二叉树的一种特殊形式,又称为最优二叉树,其主要作用在于数据压缩和编码长度的优化。

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

在这里插入图片描述

霍夫曼树的构造思路

若要使得带权外路径长度最小,可以将权值大的节点尽量靠近根节点,这样路径短一些;而权值小的节点可以适当远离根节点,因为权值小,外路径稍微长一点也没事。

应用场景

  • 霍夫曼编码
    霍夫曼编码是一种基于最小冗余编码的压缩算法。最小冗余编码是指,如果知道一组数据中符号出现的频率,就可以用一种特殊的方式来表示符号从而减少数据需要的存储空间。一种方法是使用较少的位对出现频率高的符号编码,用较多的位对出现频率低的符号编码。我们要意识到,一个符号不一定必须是文本字符,它可以是任何大小的数据,但往往它只占一个字节。

算法题应用

霍夫曼树的特性除了压缩,还可以用于一些关于最小代价问题的决策上。
例如:一个老木匠,有若干段长短不一的木头,他想把这些木头全部拼成一根,每次拼接耗费的体力是当前拼接的两段木头的长度,问老木匠最小花费多少体力。

代码实现

  1. 利用优先队列存储节点,保证队列中的节点值是有序的;
  2. 每次获取队列中的两个最小值,然后用这两个节点的和构造一个新的节点作为它们的父节,然后子节点出队,父节点入队;
  3. 循环这个过程,直到队列中只有一个节点为止,返回这个节点即可。
TreeNode hfmTree(int[] w){
    // 将所有节点存入优先队列,按照权值递增排序
    PriorityQueue<TreeNode> queue = new PriorityQueue<>(w.length, (a, b) -> a.val - b.val);
    
    for(int i=0; i<w.length; i++){
        queue.offer(new TreeNode(w[i]));
    }

    // 构造哈夫曼树
    while( queue.size() > 1 ){
        // 弹出最小的两个节点
        TreeNode node1 = queue.poll();
        TreeNode node2 = queue.poll();
        // 构造父节点
        TreeNode father = new TreeNode(node1.val + node2.val);
        father.left = node1;
        father.right = node2;
        // 父节点入队
        queue.offer( father );
    }

    return queue.poll();
}
原文地址:https://www.cnblogs.com/lippon/p/14117646.html