8哈夫曼树
8哈夫曼树

b d e c
2 3 4 5 6 7 b c d e
d
e f g f g h
f
g
h
8
h
25
3、用孩子兄弟表示法来存储
思路:用二叉链表来表示树,但链表中的两个 指针域含义不同。 左指针指向该结点的第一个孩子; 右指针指向该结点的下一个兄弟结点。
firstchild data nextsibling
100
40
21 32 g e 17 7 a
60
28 11 10 h 6 d 2 c 5 3 f
10
对应的哈夫曼编码(左0右1):
符 编码 频率 符 编码 频率
100
a
b
1100
00
0.07
0.19
a
b
000
001
0.07
0.19 0.06
0 b
0 40
1
1
0 60 1 28 1 0 6 d 0 2 c 11 1d Path Length
树的带权路径长度如何计算? WPL = 哈夫曼树则是:WPL 最小的树。
w kl k
k=1
n
经典之例:
4 d
2 c 7 a (b) 5 b
Huffman树
7 a
7 a
5
2 b c
4 d
5 b
2 c (c)
4 d
(a)
WPL=36
WPL=46
WPL= 35
3
构造霍夫曼树的基本思想: 权值大的结点用短路径,权值小的结点用长路径。 构造Huffman树的步骤(即Huffman算法):
(1) 由给定的 n 个权值{w0, w1, w2, …, wn-1},构造具有 n 棵扩充 二叉树的森林F = { T0, T1, T2, …, Tn-1 },其中每一棵扩充二叉树 Ti 只有一个带有权值 wi 的根结点,其左、右子树均为空。 (2) 重复以下步骤, 直到 F 中仅剩下一棵树为止: ① 在 F 中选取两棵根结点的权值最小的扩充二叉树, 做为左、 右子树构造一棵新的二叉树。置新的二叉树的根结点的权值为 其左、右子树上根结点的权值之和。 ② 在 F 中删去这两棵二叉树。 ③ 把新的二叉树加入 F。
树的遍历和哈夫曼树

2021/4/18 北京化工大学信息学院 数据结构 33
求二叉树高度的递归算法
int Height ( BinTreeNode * T ) { if ( T == NULL ) return -1; else { int m = Height ( T->leftChild ); int n = Height ( T->rightChild ) ); return (m > n) ? m+1 : n+1;
中序遍历 (Inorder Traversal)
中序遍历二叉树算法的框架是:
若二叉树为空,则空操作;
-
否则 中序遍历左子树 (L);
+
/
访问根结点 (V);
a *e f
中序遍历右子树 (R)。
遍历结果
b-
a+b*c-d-e/f
cd
2021/4/18 北京化工大学信息学院 数据结构 20
二叉树递归的中序遍历算法
如果 n = 0,称为空树;如果 n > 0,则 ▪ 有一个特定的称之为根(root)的结点,
它只有直接后继,但没有直接前驱; ▪ 除根以外的其它结点划分为 m (m 0)
个 互不相交的有限集合T0, T1, …, Tm-1,每 个集合又是一棵树,并且称之为根的子树。
2021/4/18 北京化工大学信息学院 数据结构 3
typedef struct node { //树结点定义
TreeData data;
//结点数据域
struct node * leftChild, * rightchild;
//子女指针域
} BinTreeNode;
typedef BinTreeNode * BinTree; //树定义,代表树的根指针
最优二叉树(哈夫曼树)的构建及编码

最优⼆叉树(哈夫曼树)的构建及编码参考:数据结构教程(第五版)李春葆主编⼀,概述1,概念 结点的带权路径长度: 从根节点到该结点之间的路径长度与该结点上权的乘积。
树的带权路径长度: 树中所有叶结点的带权路径长度之和。
2,哈夫曼树(Huffman Tree) 给定 n 个权值作为 n 个叶⼦结点,构造⼀棵⼆叉树,若该树的带权路径长度达到最⼩,则称这样的⼆叉树为最优⼆叉树,也称为哈夫曼树。
哈夫曼树是带权路径长度最短的树,权值较⼤的结点离根较近。
⼆,哈夫曼树的构建1,思考 要实现哈夫曼树⾸先有个问题摆在眼前,那就是哈夫曼树⽤什么数据结构表⽰? ⾸先,我们想到的肯定数组了,因为数组是最简单和⽅便的。
⽤数组表⽰⼆叉树有两种⽅法: 第⼀种适⽤于所有的树。
即利⽤树的每个结点最多只有⼀个⽗节点这种特性,⽤ p[ i ] 表⽰ i 结点的根节点,进⽽表⽰树的⽅法。
但这种⽅法是有缺陷的,权重的值需要另设⼀个数组表⽰;每次找⼦节点都要遍历⼀遍数组,⼗分浪费时间。
第⼆种只适⽤于⼆叉树。
即利⽤⼆叉树每个结点最多只有两个⼦节点的特点。
从下标 0 开始表⽰根节点,编号为 i 结点即为 2 * i + 1 和 2 * i + 2,⽗节点为 ( i - 1) / 2,没有⽤到的空间⽤ -1 表⽰。
但这种⽅法也有问题,即哈夫曼树是从叶结点⾃下往上构建的,⼀开始树叶的位置会因为⽆法确定⾃⾝的深度⽽⽆法确定,从⽽⽆法构造。
既然如此,只能⽤⽐较⿇烦的结构体数组表⽰⼆叉树了。
typedef struct HTNode // 哈夫曼树结点{double w; // 权重int p, lc, rc;}htn;2,算法思想 感觉⽐较偏向于贪⼼,权重最⼩的叶⼦节点要离根节点越远,⼜因为我们是从叶⼦结点开始构造最优树的,所以肯定是从最远的结点开始构造,即权重最⼩的结点开始构造。
所以先选择权重最⼩的两个结点,构造⼀棵⼩⼆叉树。
然后那两个最⼩权值的结点因为已经构造完了,不会在⽤了,就不去考虑它了,将新⽣成的根节点作为新的叶⼦节加⼊剩下的叶⼦节点,⼜因为该根节点要能代表整个以它为根节点的⼆叉树的权重,所以其权值要为其所有⼦节点的权重之和。
哈夫曼树.ppt

n
w i pi
最小,其中
i 1
Wi是第i个字符的使用频度,而Pi是第i个字符的编码长度, 这正是度量报文的平均长度的式子。
2020/3/5
21
例2:要传输的电文是{CAS;CAT;SAT;AT}
要传输的字符集是 D={C,A,S,T, ;}
每个字符出现的频率是W={ 2,4, 2,3, 3 }
PL=0+1+1+2+2=6
2020/3/5
9
问题2:什么样的带权树路径长度最小?
例如:给定一个权值序列{2,3,4,7},可构造的多种 二叉树的形态。
2
3
4
7
2 34 7
(a) WPL=2×2+2×3+2×4+2×7=32 (b) WPL=1×2+2×3+3×4+3×7=41
2020/3/5
7
4
3
2
(c) WPL=1×7+2×4+3×3+3×2=30
10
哈夫曼树的构造
例:给定权值{7,5,2,4},构造哈夫曼树。
6
方法: 75 2 4
75
(1)a 初始b化:由c 原始d数据生成森林a ; b c
d
(次2小)的找二最叉小(树a树) 作:为在左森右林子中树选构取造两一棵棵根新结的点二权叉值树最(,小b)其的根和
A)先序遍历
B)中序遍历
C)后序遍历
D)从根开始进行层次遍历
2、某二叉树的先序序列和后序序列正好相反,则该二叉
树一定是( B )的二叉树。
A)空或只有一个结点
B)高度等于其结点数
C)任一结点无左孩子
D)任一结点无右孩子
哈夫曼树和哈夫曼编码(数据结构程序设计)

课程设计(数据结构)哈夫曼树和哈夫曼编码二○○九年六月二十六日课程设计任务书及成绩评定课题名称表达式求值哈夫曼树和哈夫曼编码Ⅰ、题目的目的和要求:巩固和加深对数据结构的理解,通过上机实验、调试程序,加深对课本知识的理解,最终使学生能够熟练应用数据结构的知识写程序。
(1)通过本课程的学习,能熟练掌握几种基本数据结构的基本操作。
(2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。
Ⅱ、设计进度及完成情况Ⅲ、主要参考文献及资料[1] 严蔚敏数据结构(C语言版)清华大学出版社 1999[2] 严蔚敏数据结构题集(C语言版)清华大学出版社 1999[3] 谭浩强 C语言程序设计清华大学出版社[4] 与所用编程环境相配套的C语言或C++相关的资料Ⅳ、成绩评定:设计成绩:(教师填写)指导老师:(签字)二○○九年六月二十六日目录第一章概述 (1)第二章系统分析 (2)第三章概要设计 (3)第四章详细设计及实现代码 (8)第五章调试过程中的问题及系统测试情况 (12)第六章结束语 (13)参考文献 (13)第一章概述课程设计是实践性教学中的一个重要环节,它以某一课程为基础,可以涉及和课程相关的各个方面,是一门独立于课程之外的特殊课程。
课程设计是让同学们对所学的课程更全面的学习和应用,理解和掌握课程的相关知识。
《数据结构》是一门重要的专业基础课,是计算机理论和应用的核心基础课程。
数据结构课程设计,要求学生在数据结构的逻辑特性和物理表示、数据结构的选择和应用、算法的设计及其实现等方面,加深对课程基本内容的理解。
同时,在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。
在这次的课程设计中我选择的题目是表达式求值和哈夫曼树及哈夫曼编码。
这里我们介绍一种简单直观、广为使用的算法,通常称为“算符优先法”。
哈夫曼树又称最优树,是一类带权路径长度最短的树,有着广泛的应用。
哈夫曼树长度计算

哈夫曼树长度计算
哈夫曼树(Huffman Tree)是一种特殊的二叉树,通常用于数据压缩等领域。
在哈夫曼树中,每个叶子节点都对应一个权值(或频率),而非叶子节点的权值则等于其左右子节点权值之和。
哈夫曼树的构建过程是根据节点权值,不断选取权值最小的两个节点进行合并,直到只剩下一个根节点为止。
哈夫曼树的长度通常是指其带权路径长度(WPL,Weighted Path Length),即树中所有叶子节点的带权路径长度之和。
带权路径长度是指从根节点到该叶子节点的路径长度与该叶子节点权值的乘积。
计算哈夫曼树的长度(WPL)通常按照以下步骤进行:
根据给定的权值(或频率)构建哈夫曼树。
计算每个叶子节点的带权路径长度。
从根节点到叶子节点的路径长度可以通过从叶子节点向上回溯到根节点,累加每条边的权值得到。
叶子节点的带权路径长度则是该路径长度与叶子节点权值的乘积。
将所有叶子节点的带权路径长度相加,得到哈夫曼树的长度(WPL)。
需要注意的是,哈夫曼树的构建和长度计算通常使用优先队列(如最小堆)来优化过程,以提高效率。
在实际应用中,哈夫曼编码就是基于哈夫曼树的一种数据压缩方法,通过将出现频率
较高的字符编码为较短的二进制串,从而实现数据压缩。
哈夫曼树构造例题

哈夫曼树构造例题
假设有如下频率表:
字符 | 频率
----|------
a | 2
b | 4
c | 6
d | 8
e | 10
首先,需要将字符按照频率的从小到大的顺序排列,得到:a(2),b(4),c(6),d(8),e(10)
接下来,我们需要构造哈夫曼树:
1. 将频率最小的两个字符 a(2) 和 b(4) 组成一个节点,频率为6,得到新的频率表:
c(6),d(8),e(10),ab(6)
2. 将频率最小的两个字符 c(6) 和 ab(6) 组成一个新节点,频率为12,得到新的频率表:
d(8),e(10),abc(12)
3. 将频率最小的两个字符 d(8) 和 e(10) 组成一个新节点,频率为18,得到新的频率表:
abc(12),de(18)
4. 将最后剩下的两个节点 abc(12) 和 de(18) 组成一个新节点,得到最终的哈夫曼树。
最终的哈夫曼树如下所示:
```
30
/ \
12 18
/ \ / \
a(2) b(4) c(6) d(8) e(10)
```
根节点的频率为所有字符的频率之和,左子树和右子树分别代表相应字符的编码路径。
哈夫曼树

字符序列:DATA TRERTER ARE AREA ART 用0、1组合进行编码,希望01串长度最短。 字符集为{A,D,T,R,E},各字母出现的次 数为{6,1,4,6,4} 高频字符,译码尽可能短
一个方案
– – – – – A:10 D:010 T:011 R:11 E:00
基本术语
结点的权
– 在许多实际应用中,常常将树中的某些结 点赋上一个具有一定意义的实数,这个实 数称为该结点的权
结点的带权路径
– 从根结点到结点的路径长度*结点的权
树的带权路径WPL
– 树中所有叶子结点的带权路径长度之和
基本术语
对所有叶子结点i计算 Wi Li
计算WPL
哈夫曼树
最优树/哈夫曼树
(1)与n个权对应的结点构成具有n棵二叉 树的森林F={T1,T2,…,Tn},其中每棵二叉 树Ti都只有一个根结点,左右子树均空 (2)从F中选出根结点权值最小的两棵树 作为一棵树的左右子树,且置新树的根 结点权值为左右子树根结点权值之和 (3)从F中删除这两棵树,将新树加入F (4)重复(2)、(3),直到F中只含一棵树
哈夫曼树
哈夫曼(haffman)树又称为最优二叉树, 它是n个带权叶子结点构成的二叉树中 WPL最小的二叉树。 ??
ቤተ መጻሕፍቲ ባይዱ
– 所有叶子结点的权值均为1(或相等),构 成的二叉树形式? – 在哈夫曼树中叶子结点的权与路径长度的关 系? – 叶子数目已知,结点总数=? – 唯一性?
哈夫曼树—构造(贪心)
ht[m].codify:=“”; for i:=m downto n+1 do begin p:=ht[i].lchild; if p<>0 then ht[p].codify:=ht[i].codify+”0” p:=ht[i].rchild; if p<>0 then ht[p].codify:=ht[i].codify+”1” end;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
b d e c
2 3 4 5 6 7 b c d e
d
e f g f g h
f
g
h
8
h
25
3、用孩子兄弟表示法来存储
思路:用二叉链表来表示树,但链表中的两个 指针域含义不同。 左指针指向该结点的第一个孩子; 右指针指向该结点的下一个兄弟结点。
firstchild data nextsibling
2
Huffman树简介:
Weighted Path Length
树的带权路径长度如何计算? WPL = 哈夫曼树则是:WPL 最小的树。
w kl k
k=1
n
经典之例:
4 d
2 c 7 a (b) 5 b
Huffman树
7 a
7 a
5
2 b c
4 d
5 b
2 c (c)
4 d
(a)
WPL=36
WPL=46
9
为清晰起见,重新排序为: w={2, 3, 6, 7, 10, 19, 21, 32} ×× w1={5, × × 6, 7, 10, 19, 21, 32} w2={7, × 10, × 11, 19, 21, 32} w3={11, × 17, × 19, 21, 32} w4={19, × 21, × 28, 32} w5={28,32,40} ×× w6={40,60} × × w7={100} 哈夫曼树 19 b
WPL= 35
3
构造霍夫曼树的基本思想: 权值大的结点用短路径,权值小的结点用长路径。 构造Huffman树的步骤(即Huffman算法):
(1) 由给定的 n 个权值{w0, w1, w2, …, wn-1},构造具有 n 棵扩充 二叉树的森林F = { T0, T1, T2, …, Tn-1 },其中每一棵扩充二叉树 Ti 只有一个带有权值 wi 的根结点,其左、右子树均为空。 (2) 重复以下步骤, 直到 F 中仅剩下一棵树为止: ① 在 F 中选取两棵根结点的权值最小的扩充二叉树, 做为左、 右子树构造一棵新的二叉树。置新的二叉树的根结点的权值为 其左、右子树上根结点的权值之和。 ② 在 F 中删去这两棵二叉树。 ③ 把新的二叉树加入 F。
1
data
parents
2 3 n
结点结构 树结构
23
例1: 双亲表示法
A
B D
H I E F
C G
0 1 2 3 4 5 6 7 8
A B C D E F G H I
-1
0 0 1 1 2 2 3 3
缺点:求结点的孩子时需要遍历整个结构。
24
2、用孩子表示法来存储
思路:将每个结点的孩子排列起来,形成一个带表头 (装父结点)的线性表(n个结点要设立n个链表); 再将n个表头用数组存放起来,这样就形成一个混合 结构。 1 a c b 例如:
要点:把最右边的子树变为森林,其余右子树变为兄弟
A A E C F G H I J B A C E G B C D F E H I
G
B
J
D
D
F
H
I J
22
2. 树和森林的存储方式
树有三种常用存储方式: ①双亲表示法 ②孩子表示法 ③孩子兄弟表示法
1、用双亲表示法来存储
思路:用一组连续空间来存储树的结点,同时在每个 结点中附设一个指示器,指示其双亲结点在链表中的 data parents 位置。
怎样编码才能使它们组成的报文在网络中传得最快?
法1:等长编码。例如用二进制编码来实现。 取 d=00,i=01,a=10,n=11 法2:不等长编码,例如用哈夫曼编码来实现。 取 d=0; i=10, a=110, n=111 最快的编码是哪个? 是非等长的Huffman码!
怎样实现Huffman编码?先要构造Huffman树!
二叉树的应用
平衡树—— 特点:左右子树深度差 ≤1 排序树—— 特点:“左小右大” 字典树—— 由字符串构成的二叉树排序树 判定树—— 例如,12个球只称3次分出轻重 带权树—— 特点:路径长度带权值 最优树—— 带权路径长度最短的树,又称 Huffman
树,用途之一是通信中的压缩编码。
1
6.5
Huffman树及其应用
法二:森林直接变兄弟,再转为二叉树
(参见教材P138图6.17,两种方法都有转换示意图)
20
森林转二叉树举例:(法二)
A
B C D E G
A F
H
I
B E C F D H I J J H I G
J
A A B C E
G
D
F
兄弟相连 长兄为父 孩子靠左 头根为根
21
讨论4:二叉树如何还原为森林? 即B={root, LB, RB} F={T1, T2, …,Tm}
i 57 s 51
t
80
13
提示1:霍夫曼树中各结点的结构可以定义为如下 5个分量: char weight parent lchild Rchild
提示2:霍夫曼树的存储结构可采用顺序存储结构:
将整个霍夫曼树的结点存储在一个数组中:HT[1..n]; 将结点的编码存储在HC[1..n]中。
提示3:霍夫曼树如何构造?构造好之后又如何求得 各结点对应的霍夫曼编码?——算法参见教材P147。
c
d
11110
1110
0.02
0.06
c
d
010
011
0.02 19 0.32
0.03 0.21 0.10
e
f g h
10
11111 01 1101
0.32
0.03 0.21 0.10
e
f g h
100
101 110 111
21 32 g e 0 17 0 1
7 a 10 h
Huffman码的WPL=2(0.19+0.32+0.21) + 4(0.07+0.06+0.10) +5(0.02+0.03)
参考 资料 “数据结构”演示程序
14
二叉树小结
1、定义和性质 树
顺序结构
2、存储结构
链式结构
二叉链表
森林
二叉树
先序遍历
三叉链表
3、遍历
中序遍历
后序遍历
先序线索树
4、线索化:线索树 霍夫曼树
中序线索树 后序线索树
霍夫曼编码
15
6.4 树和森林
1. 树和森林与二叉树的转换 2. 树和森林的存储方式 3. 树和森林的遍历
例如:
b
树没有中序遍历(因子树不分左右)
a c d e
先序序列: a b c d e 后序序列: b d c e a
28
讨论:若采用“先转换,后遍历”方式,结果是否一样?
a a
先序遍历:a b c d e
b c
d
e
b c d e
中序遍历:b d c e a 后序遍历:d e c b a
结论: 1. 树的先序遍历二法相同; 2. 树的后序遍历相当于对应二叉树的中序遍历; 3. 树没有中序遍历,因为子树无左右之分。
小结:哈夫曼树及其应用 1.Huffman算法的思路: ——权值大的结点用短路径,权值小的结点用长路径。 2.构造Huffman树的步骤: 对权值的合并、删除与替换 3. Huffman编码规则: 左“0” 右“1”,是一种前缀 码 也称为最小冗余编码、紧致码,等等,它是数据压缩 学的基础。
(最优前缀编码)
设想字符串为: 100个d,10个i,2个a,2个n 法1:228位 法2: 100x1+10x2+2x3+2x3= 132 位
6
构造Huffman树的步骤:
操作要点1:对权值的合并、删除与替换
——在权值集合{7,5,2,4}中,总是合并当前值最小的两个权
注:方框表示外结点(叶子,字符对应的权值), 圆框表示内结点(合并后的权值)。
根结点肯定 没有右孩子!
a
c e
i
d
e f f g h
18
g
h
讨论2:二叉树怎样还原为树?
要点:把所有右孩子变为兄弟!
a
b d c a
b i
c
i
e
f g h
d
e
f
g
h
19
讨论3:森林如何转为二叉树?
即F={T1, T2, …,Tm} B={root, LB, RB}
法一: ① 各树先各自转为二叉树; ② 依次连到前一个二叉树的右子树上。
4
例1:霍夫曼树的构造过程
F : {7} {5} {2} {4}
7 5 2 4
F : {7} {5} {6}
7 5 6
2 4 合并{2} {4}
初始 F : {7} {11}
11 7 5 6
F : {18}
18 7 11
2 4 合并{5} {6}
5
6 2 4
5
合并{5} {6}
例2:设有4个字符d,i,a,n,出现的频度分别为7,5,2, 4
=1.44+0.92+0.25=2.61
二进制码 WPL=3(0.19+0.32+0.21+0.07+0.06+0.10+0.02+0.03)=3
11
另一种结果表示:
12
例3(实验二):设字符集为26个英文字母,其出现频 度如下表所示。 要求编程实现: 先建哈夫曼树,再利用此树对报文“This program is my favorite”进行编码和译码。
b d e