方案一:二叉树的建立和遍历具体内容:先生成一棵二叉树,
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2
第6章 树和二叉树 (Tree & Binary Tree) 6.1 6.2 6.3 6.4 6.5 树的基本概念 二叉树 遍历二叉树和线索二叉树 树和森林 Huffman树及其应用
3
先介绍二叉树的典型应用
平衡树—— 特点:所有结点左右子树深度差≤1 排序树—— 特点:所有结点“左小右大” 字典树—— 由字符串构成的二叉排序树 判定树—— 特点:分支查找树(例如12个球如何只称3次
相等= 大于> 小于<
相等= 大于> 小于<
⑧ 轻
⑥ 轻
⑦ 轻
③ 重
② 重
① 重
8
什么是带权树?
即路径带有权值。例如:
7
5
2
4
a
b
c
d
9
6.5
Huffman树及其应用
一、Huffman树 二、Huffman编码
Huffman树 Huffman编码
带权路径 长度最短 的树 是通信 中最经 典的压 缩编码
具体内容:参见严题集P149 实习5.2要求,或参见自测卷
1
第6章 树和二叉树 作业(共11题) 6.5 6.8 6.17 6.25 6.26 6.29 6.42 6.43 6.47 6.49 6.65
喻信课堂网址:http://218.199.20.98:8000/
海豚之家网址:dian.eistar.net
14
具体操作步骤:
step1:对权值进行合并、删除与替换
——在权值集合{7,5,2,4}中,总是合并当前值最小的两个权 a. 初始 c. 合并{5} {6} d. 合并{7} {11}
b. 合并{2} {4}
来自百度文库
圆框表示内结点 (合并后的权值) 方框表示外结点(叶子,字符)
15
step2:按左“0”右“1” 对Huffman树的所有分支编 号 ——将 Huffman树 与 Huffman编码 挂钩
例:设有4个字符d,i,a,n,出现的频度分别为7,5,2,4, 怎样编码才能使它们组成的报文在网络中传得最快? 法1:等长编码(如二进制编码)
令d=00,i=01,a=10,n=11,则: WPL1=2bit×(7+5+2+4)=36
法2:不等长编码(如Huffman编码)
频度高的信息 用短码,反之 用长码,传输 效率肯定高!
便分出轻重) 带权树—— 特点:路径带权值(例如长度)
最优树—— 是带权路径长度最短的树,又称
用途之一是通信中的压缩编码。
Huffman树,
4
什么是平衡二叉树( 又称AVL 树)?
性质: 所有结点左、右子树深度之差的绝对值 ≤ 1 若定义结点的“平衡因子” BF = 左子树深度 – 右子树深度
则:平衡二叉树中所有结点的BF ∈[ -1, 0, 1 ]
双亲 指针型指针
w
1 7 2 19 3 2
p
0 0 9
l
0 0 0
r
0 0 0
HT[3].parent=9
19
如何编程实现Huffman编码?
参见教材P147
先构造Huffman树HT, 再求出N个字符的Huffman编码HC。 Void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n){ *w存放n个字符的权值 if (n<=1)return; m=2*n-1; //n 0个叶子的HuffmanTree共有2n0-1个结点; HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); //0单元未用 for(p=HT,i=1; i<=n; ++i,++p,++w)*p={*w,0,0,0}; //给前n0个单元
20
(续前)再求出n个字符的Huffman编码HC
HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); //分配n个字符
编码的头指针向量(一维数组) cd=(char*) malloc(n*sizeof(char)); //分配求编码的工作空间(n)
cd[n-1]=―\0‖; //编码结束符(从cd[0]~cd[n-1]为合法空间) for(i=1;i<=n;++i){ //逐个字符求Huffman编码 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));//为第i个字 符编码分配空间 strcpy(HC[i],&cd[start]); //从cd复制编码串到HC } free(cd); //释放工作空间 }//HuffmanCoding 21
18
Huffman树和Huffman树编码的存储表示:
typedef struct{ unsigned int weight;//权值分量(可放大取整) unsigned int parent,lchild,rchild; //双亲和孩子分量 }HTNode,*HuffmanTree;//用动态数组存储Huffman树 typedef char**HuffmanCode; //动态数组存储Huffman编码表 *HuffmanTree或 HT向量
初始化
for(;i<=m; ++i,++p)*p ={0,0,0,0}; //对叶子之后的存储单元清零 for(i=n+1;i<=m; ++i){ //建Huffman树(从叶子后开始存内结点) Select(HT, i-1, s1, s2); //在HT[1…i-1]选择parent为0且weight最小的 两个结点,其序号分别为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;}
10
最优二叉树 不等长编码
一、
Huffman树(最优二叉树)
d 径: 由一结点到另一结点间的分支所构成。
a b e f
c
g
若干术语: 路
路径长度:路径上的分支数目。 例如:a→e的路径长度= 2
树长度= 10 树的路径长度:从树根到每一结点的路径长度之和。
带权路径长度: 结点到根的路径长度与结点上权的乘积(WPL)
霍夫曼编码的基本思想是——
出现概率大的信息用短码,概率小的用长码,最小冗余
分析Huffman树和编码的特点:
(1)由于Huffman树的WPL最小,说明编码所 需要的比特数最少。
这种编码已广泛应 用于网络通信中。
(2) Huffman树肯定没有度为1的结点;
(3)一棵有n 0个叶子结点的Huffman树,共有2n0-1个结点; (因为n=n0+n1+n2=2n0-1)
0
d 0
1
1 0 a 1 n
i
Huffman编码结果:d=0, i=10, a=110, n=111 WPL=1bit×7+2bit×5+3bit(2+4)=35(小于等长码的WPL=36) 特征:每一码不会是另一码的前缀,译码时可惟一复原 Huffman编码也称为前缀码
16
二、Huffman编码
令d=0;i=10,a=110,n=111,则:
WPL2=1bit×7+2bit×5+3bit×(2+4)=35
明确:要实现Huffman编码,就要先构造Huffman树
13
2. 构造Huffman树的步骤(即Huffman算法):
(1) 由给定的 n 个权值{ w1, w2, …, wn }构成n棵二叉树的集合F = { T1, T2, …, Tn } (即森林) ,其中每棵二叉树 Ti 中只有一个 带权为 wi 的根结点,其左右子树均空。
第二次上机内容预告:
(三个方案由易到难,可自选,参见自测题集实验二资料)
方案一:二叉树的建立和遍历
具体内容:先生成一棵二叉树,再用中序遍历方式打印每个 结点值,并统计其叶子结点的个数。
方案二:哈夫曼树的建立和编码器的实现
具体内容:先生成一棵哈夫曼树,再打印各字符对应的哈夫 曼编码。
方案三:哈夫曼编/译码器的设计与实现
例:判断下列二叉树是否AVL树?
-1 1 0 0 0 -1 1 0 0 -1 1 2 0
(a) 平衡树
(b) 不平衡树
5
什么是二叉排序树?
----或是一棵空树;或者是具有如下性质的非空二叉树: (1)左子树的所有结点均小于根的值; (2)右子树的所有结点均大于根的值; (3)它的左右子树也分别为二叉排序树。
7 a
7
a
5 b
2 c
4 d
4 d 7 a
5 b
5 b
2 c
4 d (c)
(a)
(b)
WPL= 36
WPL= 46
WPL= 35
Huffman树是WPL 最小的树
12
1. 构造Huffman树的基本思想:
权值大的结点用短路径,权值小的结点用长路径。
WPL最小的树
讨论:Huffman树有什么用?
最小冗余编码、信息高效传输
(2) 在F 中选取两棵根结点权值最小的树 做为左右子树构造一棵 新的二叉树,且让新二叉树根结点的权值等于其左右子树的 根结点权值之和。 (3) 在F 中删去这两棵树,同时将新得到的二叉树加入 F中。
(4) 重复(2) 和(3) , 直到 F 只含一棵树为止。这棵树便是Huffman 树。 怎样证明它就是WPL最小的最优二叉树?参考《信源编码》 Huffman树的特点:没有度为1的结点。
例:下列2种图形中,哪个不是二叉排序树 ?
5 2 1 3 4 7 9 6 4 5 10 6 3 7 8
10
1
2
8
9
(a)
(b)
想一想:对它中序遍历之后是什么效果?
6
什么是判定树? 举例: 12个球如何用天平只称3次便分出轻重?
分析: 12个球中必有一个非轻即重,即共有24种“次品”的可能性。 每次天平称重的结果有3种,连称3次应该得到的结果有33=27种。 说明仅用3次就能找出次品的可能性是存在的。 思路: 首先,将12个球分三组,每组4个,任意取两组称。会有两种情 况:平衡,或不平衡。 其次,一定要利用已经称过的那些结论;即充分利用“旧球”的 标准性作为参考。
Huffman编码举例
例1【严题集6.26③】:假设用于通信的电文仅由8个字母 {a, b, c, d, e, f, g, h} 构成,它们在电文中出现的概率分别为{ 0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.10 },试为这8个字母设计哈夫曼编 码。如果用0~7的二进制编码方案又如何? 【类同P148例2】 解:先将概率放大100倍,以方便构造哈夫曼树。 放大后的权值集合 w={ 7, 19, 2, 6, 32, 3, 21, 10 }, 按哈夫曼树构造规则(合并、删除、替换),可得到哈夫曼树。
Weighted Path Length
树的带权路径长度: 即树中所有叶子结点的带权路径长度之和
Huffman树:
带权路径长度最小的树。
11
Huffman常译为赫夫曼、霍夫曼、哈夫曼等
树的带权路径长度 如何计算? 经典之例:
WPL =
w kl k
k=1
n
树中所有叶子结 点的带权路径长 度之和
2 c
(4) Huffman编码时是从叶子走到根;而译码时又要从根走 到叶子,因此每个结点需要增开双亲指针分量(连同结点权值 共要开5个分量)
(5)用计算机实现时,顺序和链式两种存储结构都要用到。
17
如何编程实现Huffman编码?
建议1:Huffman树中结点的结构可设计成5分量形式:
char weight parent lchild rchild
7
第1次:等分3组 第2次:3旧3新
①—③ 相等=
①—④
相等= 小于<
⑤—⑧
大于> ⑤ ①—③ 相等= ④ ⑨—(11) 大于> 小于<
⑨—(11) ⑤ ①—③ 大于> 小于<
④ ⑨—(11)
第3次:1旧1新
① 小于< (12) ⑨
⑨
⑩
⑩
⑥
⑦
①
②
相等= 大于> 大于> 相等= 大于> 小于< 小于< (12) (12) 重 轻 (11) ⑩ ⑨ (11) ⑨ ⑩ 重 重 重 轻 轻 轻
建议2: Huffman树的存储结构可采用顺序存储结构: 将整个Huffman树的结点存储在一个数组HT[1..n..m]中; 各叶子结点的编码存储在另一“复合”数组HC[1..n]中。 请参见教材P149图6.27的(a)和(c)
可参考: (1)教材P147~149内容; (2)严蔚敏“数据结构”演示程序; (3)习题集P149 实习5.2要求; (4)自测卷第6章上机方案二的源程序。