📖
Data Structure
  • 基本概念
  • 线性表
    • 顺序表
    • 链表
    • 广义表
  • 栈
  • 队列
  • 字符串
  • 树
    • 二叉树
    • 二叉搜索树
    • 平衡二叉树
    • 堆
    • 哈夫曼树
  • 图
    • DFS
    • BFS
  • 排序
    • 选择排序
    • 插入排序
    • 比较选择排序和插入排序
    • 希尔排序
  • 常用算法
    • 排序
    • 二叉树遍历
    • 根据两种遍历顺序重构树
    • 二叉树深度
    • 最近公共祖先
    • 回溯集合
    • N Sum
    • union-find
  • 常用算法时间复杂度速查表
由 GitBook 提供支持
在本页
  • 1. 哈夫曼树的定义
  • 2. 哈夫曼树的构造
  • 3. 哈夫曼树的特点
  • 4. 哈夫曼编码

这有帮助吗?

  1. 树

哈夫曼树

上一页堆下一页图

最后更新于4年前

这有帮助吗?

1. 哈夫曼树的定义

带权路径长度(WPL):设二叉树有 n 个叶子节点,每个叶子结点带有权值 wkw_k wk​ ,从根节点到每个叶子结点的长度为 IkI_kIk​ ,则每个叶子结点的带权路径长度之和为: WPL=∑k=1nwkIkWPL = \sum^n_{k=1}w_kI_kWPL=∑k=1n​wk​Ik​

最优二叉树 或 哈夫曼树:WPL 最小的二叉树

2. 哈夫曼树的构造

每次把 权值最小的两棵 二叉树合并

class HuffmanNode {
    int data;
    int weight;
    HuffmanNode left;
    HuffmanNode right;

    public HuffmanNode(int weight) {
        this.weight = weight;
    }
}

public class HuffmanTree {

    public HuffmanNode huffman(HuffmanNode[] nodes) {
        PriorityQueue<HuffmanNode> minHeap = new PriorityQueue<>(Comparator.comparingInt(o -> o.weight));

        minHeap.addAll(Arrays.asList(nodes));

        while (minHeap.size() > 1) {
            HuffmanNode root = new HuffmanNode(0);
            root.left = minHeap.poll();
            root.right = minHeap.poll();
            assert root.right != null;
            root.weight = root.left.weight + root.right.weight;
            minHeap.add(root);
        }
        return minHeap.poll();
    }

    // A utility function to print preorder traversal
    // of the tree.
    // The function also prints height of every node
    public void preOrder(HuffmanNode node) {
        if (node != null) {
            System.out.print(node.weight + " ");
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    @Test
    public void test() {
        HuffmanNode[] huffmanNodes = new HuffmanNode[5];
        for (int i = 0; i < 5; i++) {
            huffmanNodes[i] = new HuffmanNode( i + 1);
        }
        HuffmanNode root = huffman(huffmanNodes);
        preOrder(root);
    }

}

3. 哈夫曼树的特点

  • 没有度为 1 的结点

  • n 个叶子结点的哈夫曼树共有 2n-1 个结点(可通过公式证明:边数 = 度数)

  • 哈夫曼树的任意非叶结点的 左右子树交换 后仍是哈夫曼树

4. 哈夫曼编码

根据出现的频率,构造哈夫曼树,这样所需的代价最小

对同一组权值 {w1,w2,⋯ ,wn}\{ w_1, w_2, \cdots , w_n \}{w1​,w2​,⋯,wn​} ,存在不同构的两棵哈夫曼树