收藏 分享(赏)

哈弗曼和最小堆的数据结构知识.ppt

上传人:hskm5268 文档编号:6861920 上传时间:2019-04-25 格式:PPT 页数:32 大小:666KB
下载 相关 举报
哈弗曼和最小堆的数据结构知识.ppt_第1页
第1页 / 共32页
哈弗曼和最小堆的数据结构知识.ppt_第2页
第2页 / 共32页
哈弗曼和最小堆的数据结构知识.ppt_第3页
第3页 / 共32页
哈弗曼和最小堆的数据结构知识.ppt_第4页
第4页 / 共32页
哈弗曼和最小堆的数据结构知识.ppt_第5页
第5页 / 共32页
点击查看更多>>
资源描述

1、数据结构补充知识,算法设计训练(2),2019/4/25,5.6 Huffman树及其应用,5.6.1 Huffman树5.6.2 Huffman编码,2019/4/25,5.6.1 Huffman树,假设有n个权值分别为w0,w1,wn-1(n2)的结点,求带权外部路径长度就是要构造一棵具有n个外部结点的扩充二叉树,每一个外部结点ki取wi作为它的权,li表示该外部结点的路径长度,则带权外部路径长度可记作其中带权外部路径长度最小的二叉树称为Huffman树,2019/4/25,5.6.1 Huffman树,例如,图5.18中表示了三棵具有4个外部结点的二叉树,各外部结点的权值分别为6,2,3

2、,4。 它们的带权外部路径长度分别为: (a) 62 + 22 + 32 + 42 = 30 (b) 62 + 23 + 33 + 41 = 31 (c) 61 + 23 + 33 + 42 = 29 其中,5.18(c)中所示的二叉树外部带权路径长度最小。可以验证, 它就是一棵Huffman树,也就是说,这棵树在所有的具有6,2,3, 4权值的叶结点的二叉树中带权外部路径长度最小。,图5.18 具有不同带权外部路径长度的二叉树,2019/4/25,5.6.1 Huffman树,建立Huffman编码树: (1) 对于给定的n个权值w0,w1,wn-1(n2),构成n棵二叉树的集合T = T0

3、,T1,T2,Tn1,使得每一棵扩充二叉树只具有一个带权为wi的根结点。 (2) 构造一棵新的扩充二叉树,在集合T中找出两个权值最小的树作为新树根结点的左右子树,把新树根结点的权值赋为其左右子树根结点的和。 (3) 在集合T中删除这两棵树,并把得到的新扩充二叉树加入到集合中。 (4) 重复步骤(2)、(3)的操作,直到集合T中只含有一棵树为止。,2019/4/25,5.6.1 Huffman树,图5.19 Huffman树的构造过程,2019/4/25,5.6.1 Huffman树,【代码5.12】 Huffman树的类定义 template class HuffmanTree private

4、:HuffmanTreeNode *root; / Huffman树的根结点void MergeTree ( HuffmanTreeNode ,2019/4/25,5.6.1 Huffman树,template HuffmanTree:HuffmanTree(T weight, int n) MinHeap heap(n); / 最小值堆HuffmanTreeNode *parent, firstchild, secondchild;HuffmanTreeNode *NodeList = new HuffmanTreeNoden;for (int i = 0;i n;i+) / 初始化Node

5、Listi.info = weighti;NodeListi.parent = NodeListi.left = NodeListi.right = NULL;heap.Insert(NodeListi); / 向堆中添加元素for (i = 0;i n-1;i+) / 通过n-1次合并建立Huffman树,2019/4/25,5.6.1 Huffman树,parent = new HuffmanTreeNode; / 申请一个分支结点firstchild = heap.RemoveMin(); / 选择权值最小的结点secondchild = heap.RemoveMin(); / 选择权值

6、次小的结点MergeTree(firstchild,secondchild,parent);/ 将权值最小的两棵树合并到parent树heap.Insert(*parent); / 把parent插入到堆中去root = parent; / Huffman树的根结点赋为parentdelete NodeList; ,2019/4/25,5.6.2 Huffman编码,Huffman树的一个重要应用就是解决数据通信中的二进制编码问题。设 D=d0,dn1,W=W0,Wn1D为需要编码的字符集合,W为D中各字符出现的频率,要对D里的字符进行二进制编码,使得:最小,其中,li为第i个字符的二进制编码

7、长度。 由此可见,设计电文总长度最短的编码问题就转化成了设计字符出现频率作为外部结点权值的Huffman树的问题。,2019/4/25,5.6.2 Huffman编码,Huffman编码过程如下: 用d0,d1,dn1作为外部结点构造具有最小带权外部路径长度的扩充二叉树 把从每个结点引向其左子结点的边标上号码0,从每个结点引向其右子结点的边标上号码1 从根结点到每个叶结点路径上的编号连接起来就是这个外部结点所代表字符的编码。得到的二进制前缀码就称作Huffman编码,2019/4/25,图5.20 Huffman编码示例,2019/4/25,5.6.2 Huffman编码,例如,在一个数据通信

8、系统中使用的字符是a,b,c,d,e,f,g,对应的频率分别为15,2,6,5,20,10,18。各字符的二进制编码为: a:00 b:11110 c:1110 d:11111 e:10 f:110 g:01,2019/4/25,5.6.2 Huffman编码,用Huffman算法构造出的扩充二叉树给出了各字符的编码,同时也用来译码 从二叉树的根开始,把二进制编码每一位的值与Huffman树边上标记的0,1相匹配,确定选择左分支还是右分支,直至确定一条到达树叶的路径。一旦到达树叶,就译出了一个字符。然后继续用这棵二叉树继续译出其它二进制编码,2019/4/25,5.5 堆与优先队列,5.5.1

9、 堆的定义及其实现 5.5.2 优先队列,2019/4/25,5.5.1 堆的定义及其实现,最小值堆:最小值堆是一个关键码序列K0,K1,Kn-1,它具有如下特性: KiK2i+1 (i=0,1, n/2-1) KiK2i十2,2019/4/25,5.5.1 堆的定义及其实现,堆的性质 从逻辑的角度来讲,堆是一种树形结构,而且是一种特殊的完全二叉树。此完全二叉树的每个结点对应于序列中的一个关键码,根结点对应于关键码K0,按层次从左至右依次类推。说其特殊,主要是因为堆序只是局部有序,即最小堆对应的完全二叉树中所有内部结点的值均不大于其左右孩子的关键码值,而一个结点与其兄弟之间没有必然的联系。最小

10、堆不像二叉搜索树那样实现了关键码的完全排序。相比较而言,只有当结点之间是父子关系的时候,才可以确定这两个结点关键码的大小关系。,2019/4/25,5.5.1 堆的定义及其实现,关键码序列K = 12,14,15,19,20,17,18,24,22,26所对应的最小堆形成的完全二叉树形式为图5.14所示:,图5.14 最小堆对应的完全二叉树,2019/4/25,5.5.1 堆的定义及其实现,图5.15 在最小堆5.14中插入元素13,12,15,14,20,19,18,17,13,24,26,22,2019/4/25,5.5.1 堆的定义及其实现,图5.16 在最小堆5.14中删除元素14,1

11、2,15,14,20,19,18,17,24,26,22,2019/4/25,5.5.1 堆的定义及其实现,建堆过程: 首先将所有关键码放到一维数组中,这时形成的完全二叉树并不具备最小堆的特性,但是仅包含叶子结点的子树已经是堆即在有n个结点的完全二叉树中,当i n/2-1时,以关键码Ki为根的子树已经是堆。这时从含有内部结点数最少的子树(这种子树在完全二叉树的倒数第二层,此时i = n/2-1 )开始,从右至左依次调整对这一层调整完成之后,继续对上一层进行同样的工作,直到整个过程到达树根时,整棵完全二叉树就成为一个堆了,2019/4/25,5.5.1 堆的定义及其实现,对于关键码集合K = 1

12、9,8,35,65,40,3,7,45,用筛选法建堆的过程。其中n = 8,n/2-1=3,所以从K3 = 65开始调整。,19,8,35,7,3,40,65,45,以k3为根的子树6545 调整,以k2为根的子树353 调整,以k1为根的子树840,845 无需调整,以k0为根的子树193 调整,197 调整,图5.17 建堆过程示例,2019/4/25,堆的类定义和筛选法(1),代码5.11 堆的类定义和筛选法 template class MinHeap / 最小堆类定义 private:T *heapArray; / 存放堆数据的数组int CurrentSize; / 当前堆中元素数

13、目int MaxSize; / 堆所能容纳的最大元素数目void swap(int pos_x, int pos_y); / 交换位置x和y的元素void BuildHeap(); / 建堆 public:,2019/4/25,堆的类定义和筛选法(2),public:MinHeap(const int n); / 构造函数,n表示 堆的最大元素数目virtual MinHeap()delete heapArray; / 析构函数bool isEmpty( ); / 如果堆空,则返回真bool isLeaf(int pos) const; / 如果是叶结点,返回TRUEint leftchild

14、(int pos) const; / 返回左孩子位置int rightchild(int pos) const; / 返回右孩子位置int parent(int pos) const; / 返回父结点位置bool Remove(int pos, T,2019/4/25,堆的类定义和筛选法(3),template MinHeap:MinHeap(const int n) if (n bool MinHeap:isLeaf(int pos) const return (pos = CurrentSize/2) ,2019/4/25,堆的类定义和筛选法(4),template int MinHeap

15、:leftchild(int pos) const return 2*pos + 1; / 返回左孩子位置 template int MinHeap:rightchild(int pos) const return 2*pos + 2; / 返回右孩子位置 template int MinHeap:parent(int pos) const return (pos-1)/2; / 返回父结点位置 template bool MinHeap:Insert(const T ,2019/4/25,堆的类定义和筛选法(5),template T ,2019/4/25,堆的类定义和筛选法(6),temp

16、late void MinHeap:SiftUp(int position) / 从position向上开始调整int temppos = position;T temp = heapArraytemppos;while (temppos0) ,2019/4/25,堆的类定义和筛选法(7),template void MinHeap:SiftDown(int left) /从left开始向下筛选int i = left; / 标识父结点int j = leftchild (i); / 标识关键值较小的子结点T temp = heapArrayi; / 保存父结点while (j heapArr

17、ayj + 1)/若有右子节点,且小于左子节点j+; / j指向右子结点if (tempheapArrayj) /若父节点大于子节点的值则交换位置heapArrayi = heapArrayj;i = j;j = leftchild(j); else break; /堆序满足,跳出heapArrayi = temp;,2019/4/25,建堆效率,对于n个结点的堆,其对应的完全二叉树的层数为logn。 设i表示二叉树的层编号,则第i层上的结点数最多为2i(i 0)。 建堆的过程中,对每一个非叶子结点都调用了一次SiftDown调整算法,而每个数据元素最多向下调整到最底层,即第i层上的结点向下调

18、整到最底层的调整次数为logn i。因此,建堆的计算时间为(公式5.3)令j = logn i,代入5.3式得(公式5.4),2019/4/25,建堆效率,建堆算法的时间复杂度是O(n)。这就说明可以在线性时间内把一个无序的序列转化成堆序 由于堆有log n层深,插入结点、删除普通元素和删除最小元素的平均时间代价和最差时间代价都是(log n) 最小堆只适合于查找最小值,查找任意值的效率不高,2019/4/25,5.5.2 优先队列,优先队列(priority queue)是一种有用的数据结构。它是0个或多个元素的集合,每个元素都有一个关键码值,执行的操作有查找、插入和删除一个元素。 优先队列的主要特点是支持从一个集合中快速地查找并移出具有最大值或最小值的元素。最小优先队列,适合查找和删除最小元素;最大优先队列中,适合查找和删除最大元素。,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 网络科技 > 数据结构与算法

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报