数据结构-chapter32_part5Huffman树

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(3) 在 F 中删除这两棵树,同时将新得到的二叉树加入 集合 F 中。
(4) 重复 (2) 和 (3) ,直到 F 中只含一棵树为止。
构造Huffman编码树
例, 4 个叶子结点 a、b、c、d,分别带权7、5、2、4。
初始
a 7 1b85 11 c 2 6 d 4
a 7 b 5 11 c 62 d 4
ACEA 编码为 0110 1110 110 0110 如何译码? A C E A
1. 从根结点出发,从左至右扫描编码, 2. 若为 ‘0’ 则走左分支,若为‘1’ 则走右分支,直至叶结点为止, 3. 取叶结点字符为译码结果,返回重复执行 1,2,3 直至全部译完为止
13/98
Huffman树类
template <class T> class HuffmanTree { private:
Huffman编码树
假设有n个权值 {w0,w1, … wn-1} ,试构造一棵 有n个叶子结点的二叉树,每个叶子结点带权 为 wi ,则其中带权路径长度WPL最小的二叉 树称做最优二叉树。 Huffman树是最优二叉树。
构造Huffman编码树
(1) 根据给定的 n 个权值 {w1,w2, … wn} 构成 n 棵二叉树 的集合 F = {T1,T2, … Tn},其中每棵二叉树 Ti 中只有一 个权值为 wi 的根结点。 (2) 在 F 中选取两棵根结点权值最小的树作为左、右子 树构造一棵新的二叉树,且置新二叉树的根结点的权值 为其左、右子树根结点的权值之和。
–权越大的叶结点离根越近;如果某个叶结点的权较 小,可能就会离根较远
例,3 棵二叉树,都有 4 个叶子结点 a、b、c、d,分别带权7、5、 2、4,求它们各自的带权路径长度。
a7 b 5 c 2 d 4 (1)
c2 a7
d4
b5
a7 b 5
c 2 d4
(2)
(3)源自文库
(1) WPL = 7×2 + 5×2 + 2×2 + 4×2 = 36 (2) WPL = 7×3 + 5×3 + 2×1 + 4×2 = 46 (3) WPL = 7×1 + 5×2 + 2×3 + 4×3 = 35
A (0110) B (10) C (1110) D (1111) E (110) F (00) G (0111) H (010)
100
0
1
42 01
58 01
F 23
19
01
B 29
29
01
H 11
8
01
E 14
15
01
A5 G3
C7 D8
A (0110) B (10) C (1110) D (1111) E (110) F (00) G (0111) H (010)
b5 c 2 6 d 4
c 2 d4
编码
电文
二进制
编码
二进制 译码 电文
例,传送 ABACCD,四种字符,可以分别编码为 00,01,10,11。 则原电文转换为 00 01 00 10 10 11。 对方接收后,采用二位一分进行译码。
编码
为电文编码时,总是希望总长越短越好, 如果对每个字符设计长度不等的编码,且让电文中出 现次数较多的字符采用较短的编码,则可以减短电文 的总长。
Huffman树的构造
for(i=0;i<n-1;i++)
{//通过n-1次合并建立Huffman树
parent=new HuffmanTreeNode<T>;
firstchild=heap.RemoveMin(); //选择权值最小的结点
secondchild=heap.RemoveMin(); //选择权值次小的结点
HuffmanTreeNode<T>* root;//Huffman树的树根 //把ht1和ht2为根的Huffman子树合并成一棵以parent为 //根的二叉树 void MergeTree(HuffmanTreeNode<T> &ht1,
HuffmanTreeNode<T> &ht2, HuffmanTreeNode<T>* parent);
• 上机作业
– 3.4.1 图像压缩算法
Huffman树类
//删除Huffman树或其子树 void DeleteTree(HuffmanTreeNode<T>* root); public: //构造Huffman树,weight是存储权值的数组,n是数组长度 HuffmanTree(T weight[],int n); //析构函数 virtual ~HuffmanTree(){DeleteTree(root);}; }
例, A , B , C , D 前缀编码可以为 0 , 110 , 10 , 111
利用二叉树设计二进制前缀编码。
叶子结点表示 A , B , C , D 这 4 个字符 左分支表示 ‘0’,右分支表示 ‘1’ 从根结点到叶子结点的路径上经过的二 进制符号串作为该叶子结点字符的编码 路径长度为编码长度 证明其必为前缀编码
例,某通信可能出现 A B C D E F G H 8 个字符,其概率分别为 0.05 , 0.29 , 0.07 , 0.08 , 0.14 , 0.23 , 0.03 , 0.11 ,试设计Huffman编码 不妨设 w = { 5 , 29 , 7 , 8 , 14 , 23 , 3 , 11 }
A(0)
01
B(110) C(10)
A
D(111)
01
C 01
B
D
Huffman编码
设每种字符在电文中出现的概率 wi 为,则依此 n 个字 符出现的概率做权,可以设计一棵Huffman树,使
WPL = ∑n-1wi li 最小
i=0
wi 为叶子结点的出现概率 ( 权) li 为根结点到叶子结点的路径长度
//合并权值最小的两棵树
MergeTree(firstchild,secondchild,parent);
heap.Insert(*parent);
//把parent插入到堆中去
root=parent;
//建立根结点
}//end for
delete []NodeList;
}
作业
• 纸面作业:
– P142:15
数据结构、算法及应用
*** 二叉树
Huffman树
主要内容
• Huffman树 • Huffman编码
Huffman编码树
• 要求给出一个具有n个外部结点的扩充二叉树
–该每个外部结点Ki有一个wi与之对应,作为该外部 结点的权
–叶结点带权外部路径长度总和
n
WPL
=

i=1
wi
li
最小
(注意不管内部结点,也不用有序)
例,对 ABACCD 重新编码,分别编码为 0 , 00 , 1 , 01。 ABCD
则原电文转换为 0 00 0 1 1 01。 减短了。 问题: 如何译码?
前四个二进制字符就可以多种译法。
AAAA
BB
前缀编码
若设计的长短不等的编码,满足任一个编码都不是另一个编
码的前缀,则这样的编码称为前缀编码。
排序后 w = { 3812474920,051,81}25,53987,81,},4128192,1,1,}1,52139,4,2,}1,32429,3,2}2,932}9, 2}9 }
100
0
1
42 01
58 01
F 23
19
01
B 29
29
01
H 11
8
01
E 14
15
01
A5 G3
C7 D8
Huffman树的构造
template<class T> HuffmanTree<T>::HuffmanTree(T weight[], int n) {
//定义最小值堆 MinHeap<HuffmanTreeNode<T>> heap(n); HuffmanTreeNode<T> *parent, firstchild,secondchild; HuffmanTreeNode<T>* NodeList=new HuffmanTreeNode<T>[n]; for(int i=0;i<n;i++){ NodeList[i].element=weight[i]; NodeList[i].parent=NodeList[i].left=NodeList[i].right=NULL; heap.Insert(NodeList[i]);//向堆中添加元素 }//end for
相关文档
最新文档