Huffman 编码

进阶

Huffman 编码用贪心合并最小频率节点来缩短平均码长。

Huffman 编码

输入正整数频率,观察 Huffman 树的构建过程。

AlgoAnim · Huffman 编码

待机

速度
待机
// 源代码
1struct Node {
2    int freq;
3    char ch;
4    Node *left, *right;
5};
6
7struct Cmp {
8    bool operator()(Node* a, Node* b) { return a->freq > b->freq; }
9};
10
11Node* buildHuffman(vector<pair<char,int>>& freqs) {
12    priority_queue<Node*, vector<Node*>, Cmp> pq;
13    for (auto& [ch, f] : freqs)
14        pq.push(new Node{f, ch, nullptr, nullptr});
15    while (pq.size() > 1) {
16        Node* a = pq.top(); pq.pop();
17        Node* b = pq.top(); pq.pop();
18        pq.push(new Node{a->freq + b->freq, 0, a, b});
19    }
20    return pq.top();
21}

复杂度分析

时间 O(n log n)
空间 O(n)
最优 O(n) 两字符时
最坏 O(n log n)

算法讲解

Huffman 编码的核心是:每次从所有可用节点中取出频率最小的两个合并,形成一棵带权路径长度最小的二叉树。

频率高的字符离根更近,编码更短;频率低的字符离根更远,编码更长。

因为任何前缀编码都对应一棵二叉树,而 Huffman 树的带权路径长度是最小的,所以平均码长最优。

理解它的关键是把"合并"和"贪心"联系起来:每次选最小两个,不会让后续选择变得更差。