第6讲 Huffman编码和Huffman树

1.Huffman编码和Huffman树

(1) Huffman编码
a. 前缀编码: 是指对字符集进行编码时,要求字符集中任一字符的编码都不是其它字符的编码的前缀

​ b. 树的带权路径长度(WPL)

image-20210728153148912

​ c. 构造过程

1.所有点的度数必不为1

2.一定存在一个最优解,权最小的2个点互为兄弟

最优解 36<58

每次取最小的2个合并

image-20210728153909814

(2) Huffman树

AcWing 148. 合并果子

c++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

int main()
{
int n;
cin>>n;

priority_queue<int , vector<int>,greater<int> > heap ;// 小根堆

while (n -- ){
int x;
cin>>x;
heap.push(x);
}

int res = 0;

while(heap.size()>1){
int a = heap.top();heap.pop(); //当前最小值
int b = heap.top();heap.pop(); // 当前次小值
res += a+b;
heap.push(a+b);

}

cout<<res<<endl;
return 0;
}

扩展:之前是2进制编码 ,及二叉树

当为 K 进制编码 , K叉树 ,类同二叉树

每次合并 最小的 K 个数

每次减少k 个数 ,n >>> n-(k-1) 最后是否能 (n-1)/(k-1)??? (n点数 k分叉数)

这时候我们在前面补0使其能整除 0不提供代价补任意个都可

二叉树中因为 k-1 = 1不用考虑

AcWing 149. 荷马史诗

有点难

2.考题:2012-41、2013-4、2014-6、2015-3、2017-6、2018-5、2019-3、2020-42

2012-41

image-20210728161258963

归并 $O(n+m-1)$

image-20210728161639481

image-20210728161737527

2013-4

image-20210728161822342

(6-1)/ (3-1) 不能整除 前添加0

image-20210728162126981

$ (2+3)3 + (4+5)2+ (6+7)*1 = 46$

$ 5+14+27 = 46$

2014-6

image-20210728162447688

D

2015-3

image-20210728162700250

D

image-20210728162921582

2017-6

image-20210728163010077

D

image-20210728163135924

2018-5

image-20210728163220424

A

image-20210728163442240

2019-3

image-20210728163516141

C

image-20210728163650638

2020-42

image-20210728163752420

  1. Huffman 树

  2. 0/1 串到字符串

    从根节点到叶节点每一个0/1表示一个字符,遍历到叶节点后回到根节点

  3. 判断所以字符是否为叶节点

image-20210728164904409