哈夫曼树与哈夫曼编码

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。



要将文本编码成 0/1 序列(数字信号) 由数字序列可以直接解码得到原始文 本
待编码文本中,各字符出现概率不 同 平均编码长度:各字符的编码 平均编码长度
长度与出现概率之积求和 平均编码长度较短的编码方案 具有更好的性能
方案 1:

定长编码
编码:所有字符编码等 编码 解码:
哈夫曼树:带权路径长度最小的二叉树。 在哈夫曼树中,权值越大的结点离根越近。
练习:构造哈夫曼树
5 7 12 15 22 39
5 12 7
5
12
15
22
39
15
22 12
24 12 7
39
100 61 24 12 5 7 12 15 37 22 39
61 24 12 5 7 12 15 37
39
24 12 5 7 12 15

结点结构设计
由于一棵 n 个叶结点的哈夫曼树共有 2n-1
个结点,故可以用一个大小为 2n-1 的一维 数组存储哈夫曼树。具体数组元 素 的结构 是: 权 值 双亲 左 孩子 右孩子 typedef struct { unsigned int weight; unsigned int parent, lchild, rchild; }HTNode, *HuffmanTree;
基本概念( 1 )
最优二叉树 路径长度 (Path
100
Length) : 连接两 结点的路径上的分 支数。 结点的带权路经长 度 :从根结点到该 结点之间的路径长 度与结点上权的乘 积。
42
58
19 11 3 8
23 14 5
Βιβλιοθήκη Baidu
29 15 7 8
29
基本概念( 2 )
树的带权路经长度 :树中

001,010,011 ⇒ b,c,d
平均编码长度:
方案 2:

变长编码
编码: 编码
给出现概率大的字 符以较短的编码 而给出现概率小的 字符以较长的编码
按概率顺序:

b>e>c>a>d
如何解码?
b,c,d ⇒ 0, 00,10
方案 3:

前缀编码
编码: 编码
任一字符编码都不 是其他字符编码的 前缀
void CreatHuffman(HuffmanTree &HT,HuffmanCode &HC, int *w, int n) { // 构造哈夫曼树 HT if (n<=1) return; m=2*n-1; HT=(HuffmanTree)malloc((m+1)+sizrof(HTCode)); InitHummanTree(HT); // 将 HT[0..m] 中结点的 三指针域 都 设置 // 为 0, 并 填好权值; /* for(p=HT, i=1; i<=n; ++i, ++p, ++w) *p={*w, 0, 0, 0}; for ( ; i<=m; ++p) *p={0,0,0,0} */ for (i=n+1; i<=m; i++) { // 构造哈夫曼树 Select(HT, i-1,&s1,&s2); // 选取 两个权值最小的结点 HT[s1].parent=i; HT[s2].parent=i; HT[i].lchild=s1; HT[i].rchild=s2; HT[i].weight=HT[s1].weight+HT[s2].weight; } HuffmanEncoding(HT, HC); // 从叶子到根 逆向 求每个叶结点 的
void SelectMin(HuffmanTree T, int i, unsigned int *s1, unsigned int *s2) { int j; unsigned int firstmin,secondmin; firstmin=secondmin=32767; for (j=1; j<i; j++) { // 求最小值 if ((T[j].parent==0)&&(T[j].weight<firstmin)) { firstmin=T[j].weight; *s1=j;} } for (j=1; j<i; j++) { // 求次小值 if ((T[j].parent ==0) && (T[j].weight!=firstmin) && (T[j].weight <secondmin)) { secondmin=T[j].weight ; *s2=j;} } }
平均编码长度: 平均编码长度
显然,变长编码比定
长编码具有更好性能
b,c,d ⇒ 11, 01,001
问题:能否有性能更好的变长编码方案 ?
方案 4:
技术
哈夫曼编码
D.Huffman 于 1952 年提出的一种无失真压缩 该方法完全依据字符出现概率来构造平均长
度最短的编码,也称为最佳编码
编写哈夫曼树字符编码
依次从叶结点出发, 向 上 回溯 直到根。上 溯
时 走 左分支则 生 成 代 码 0 , 走 右分支则 生 成 代 码 1 。所得编码是 反向 的哈夫曼编码。 正向读取 编码,即得到需要结 果 。 typedef Char **HuffmanCode;
HC
void HuffmanEncoding(HuffmanTree HT, HuffmanCode &HC) {// 根据哈夫曼树 HT 求哈夫曼编码 表 HC HC=(HuffmanCode)malloc((n+1)*sizeof(char *)); cd=(char *)malloc(n*sizeof(char));// 分 配 求编码的 工 作 空 间 cd[n-1]=“\0”; // 编码结 束 符 for (i=1; i<=n; ++i) { start=n-1; for (c=i, f=HT[i].parent; f!=0; c=f, f=HT[f].parent) if (HT[f].lchild==c) cd[--start]=“0”;// 为左子树结点 else cd[--start]=“1”; // 为右子树结点 HC[ i ]=(char *)malloc((n-start)*sizeof(char)); strcpy(HC[ i ], &cd[start]); } free(cd); // 释放工 作 空 间 }//HuffmanEnCoding
所有 叶子结点 的带权路径 长度之和。记作:
WPL =
100
∑w l
k =1
n
42
58
k k
WPL=11*3+3*4+5*4+7* 4+8*4+14*3+29*2+23*2 =33+12+20+28+32+42 +58+46=291
19 11 3 8
23 14 5
29 15 7 8
29
具有不同带权路径长度的二叉树
哈夫曼树 (Huffman Tree)
图像处理中如何对图像数据进行编码,可以 图像处理
实现图像文件压缩?
通信中如何对待传送的信息进行编码,可以 通信
减少对通信信道带宽的需要? 例如:某段待发送的信息中含有字母 A, E, I, O, U, D, T, B ,它们各自出现的概率是: 0.05, 0.29, 0.07, 0.08, 0.14, 0.23, 0.03, 0.11 , 问如何对该 8 个字母编码,可以使得传送的 信息编码最短?
满足前缀码的性质,因此可以即时解码
哈夫曼树:
平均编码长度:
练习:哈夫曼编码
0 42 0 19 0 8 0 3 1 5 1 11 14 1 23
100 1 58 0 0 29 1 15 1 8 1 29
0 7
3: 0000; 5:0001; 7: 1010; 8: 1011; 11: 001; 14: 100; 23: 01; 29: 11
37 22
39
22
哈夫曼树的特点
二叉树的 WPL 最小; 一组数据的哈夫曼树不唯一; 哈夫曼树上无度为 1 的结点 。

问题 :一棵有 n 个叶子结点的哈夫曼树共有 几个结点? 求解: 因为 n0=n2+1, 当 n0=n ,则 n2=n-1 , 共有 2n-1 个结点
编码问题
设有字符集: S={a,b,c,d,e} 组成的文
哈夫曼编码的不足
需要精确统计文本中字符出现概率 编码速度较慢 没有错误保护功能 尽管如此,哈夫曼码还是得到了广泛的应用
, JPEG 和 MPEG 中均有其身影
huffman 算法实现
构造哈夫曼树
从叶结点开始按构造哈夫曼树的算法构造哈 夫曼树; ( 确立双亲、孩子关系,建立度为 2 的结点,填写双亲、孩子关系信息,完成 从下到上的结点链接 ) 编写哈夫曼码 从根结点开始设二叉树的左子树编码 为‘ 0’ ,右子树编码为‘ 1’ ,依次编码下 去直到叶结点,然后从根到每个叶结点依次 写出叶结点的编码——哈夫曼编码。 ( 按照 孩子信息完成从上到下的结点编码。
相关文档
最新文档