一、平衡二叉树

1.1 什么是平衡二叉树?

规定在插入和删除二叉树结点时,要保证任意结点的左、右子树高度之差的绝对值不可以超过1

平衡因子:结点左子树和右子树的结点高度差为该结点的平衡因子,也就是说平衡树的平衡因子只可能是-1,0,1

如下图,结点53左子树高度为3,右子树高度为2,所以结点53的平衡因子为1

1.2 为什么需要平很二叉树?

为了避免树的高度增长过快,降低二叉树的性能

如下图,左边的图的最坏查找情况为O(n),而右边图的最坏查找情况为O(logn)

1.3 平衡二叉树的机制?

总纲:调整过程应该是自下而上的

无论是插入还是删除,改变一个结点的位置就会导致一棵二叉树的平衡因子改变。因此,在每插入或者删除一个结点之后,需要重新计算二叉树各个结点的平衡因子。若右结点的平衡因子大于1,那么需要调整这棵二叉树为平衡二叉树。当该树再次称为平衡二叉树之后,再进行下一步的插入或删除操作。

1. LL型

口诀:左失衡,中为支,高右旋

解释:如果对于LL型二叉树转为平衡二叉树不是很了解,背口诀套就是了。但是,终究要了解为什么这么做。在这一步的过程中,其实不需要死记硬背,只需要记住每一步的调整满足二叉排序的性质和定义,然后从整棵二叉树分析,在{20,23,45},平衡因子在结点45时绝对值大于1,这么调整{20,23,45}为一棵平衡二叉树。显然,让中间结点23(23大于20且小于45)作为根,结点20和结点45分别作为结点23的左右孩子结点,符合调整意图

调整过程如下图所示

2. RR型

口诀:右失衡,中为支,高左旋

解释:同样的道理。从整棵二叉树分析,在{65,70,75},平衡因子在结点65时绝对值大于1,这么调整{65,70,75}为一棵平衡二叉树。显然,让中间结点70(70大于65且小于75)作为根,结点65和结点75分别作为结点70的左右孩子结点,符合调整意图

调整过程如下图所示

3. LR型

口诀:下二整体左旋,后与LL型调整一样

解释:下二整体左旋的目的就是在局部形成类似LL型失衡情况一样。在这一步的过程中(下二整体左旋),同样不需要死记硬背,只要满足一棵二叉排序树就可以。比如下图的操作,将结点25作为结点23的双亲结点,同时,23比25小,所以结点23是结点25的左孩子结点。此时,整棵树就是LL型的二叉树

调整过程如下图所示

4. RL型

口诀:下二整体右旋,后与RR型调整一样

解释:下二整体右旋的目的就是在局部形成类似RR型失衡情况一样。在这一步的过程中,将结点68作为结点70的双亲结点,同时,70比68大,所以结点70是结点68的右孩子结点。此时,整棵树就是RR型的二叉树,做RR调整就可以了

调整过程如下图所示

二、哈夫曼树

1.1 什么是哈夫曼树?

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树

在深入了解哈夫曼树之前,我们需要先知道一些必要的基本概念。

  1. 路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
  2. 结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
  3. 树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL(Weighted Path Length)。

如下图:

图a:WPL=7∗2+5∗2+2∗2+4∗2=36WPL=7*2+5*2+2*2+4*2 = 36WPL=7∗2+5∗2+2∗2+4∗2=36

图b:WPL=7∗3+5∗3+2∗1+4∗2=46WPL=7*3+5*3+2*1+4*2 = 46WPL=7∗3+5∗3+2∗1+4∗2=46

图c:WPL=7∗1+5∗2+2∗3+4∗3=35WPL=7*1+5*2+2*3+4*3 = 35WPL=7∗1+5∗2+2∗3+4∗3=35

比较得知:图c中树的WPL最小,所以图3为一棵哈夫曼树

1.2 为什么使用哈夫曼树?

在计算机数据处理中,哈夫曼编码使用变长编码表对源符号进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

简单的来说,就按出现的频率不同,把高频率出现的目标放在距离根结点近的位置,低频率出现的目标放在距离根结点源的位置,这样就使得查找效率提高。

1.3 如何使用哈夫曼树?

给定n个权值分别为 w1,w2,…,wnw_1,w_2,…,w_nw1​,w2​,…,wn​ 的结点,通过哈夫曼算法可以构造出最优二叉树。

  1. 将这n个结点分别作为n棵仅含一个结点的二叉树,构成森林。
  2. 构成一个新的结点,从森林中选取两棵根结点最小的树作为新结点的左、右子树,并且将新结点的的权值置为左、右子树上根结点的权值和
  3. 从森林中删除步骤2选出的树,同时将新得到的树放入森林中
  4. 重复步骤2和3,直到森林中只剩下一棵树

哈夫曼树有如下特点:

  1. 每个初始结点最终都成为叶结点,且权值越小的结点到根结点的路径越长
  2. 构造过程中共新建了n−1n-1n−1个结点,因此哈夫曼树中的结点总数为 2n−12n-12n−1
  3. 每次构造都选择2棵树作为新结点的孩子,因此哈夫曼树中不存在度为1的结点

哈夫曼树的构造过程


最后稳一点,大家认为哈夫曼树是唯一的嘛?显然不是。因为二叉树是分左右结点的,比如上图(c)中,结点c是双亲结点的左孩子结点,结点d是双亲结点的右孩子结点,二者交换位置也是可以的,并不影响整棵树是一棵哈夫曼树(WPL没有改变)。所以哈夫曼树答案不唯一。

1.4 哈夫曼编码

为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度。

因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。利用哈夫曼树来设计二进制的前缀编码,既满足前缀编码的条件,又保证报文编码总长最短。

若没有一个编码是另一个编码的前缀,则称这样的编码为前缀编码。

通过前缀编码解码,可以辨识出第一个编码,并将编码翻译为源原码。

例如:00101100,可以唯一被解读为:0、0、101、100

下面举个例子

a:01

b:10

c:110

d:111

e:00

通过上面的例子可以看出,对于每个叶子结点上的值都有唯一的编码

【数据结构-树】4.图解平衡二叉树和哈夫曼编码(逐步演绎,一文读懂)相关推荐

  1. 哈夫曼树(Huffman Tree),与哈夫曼编码

    目录 一.哈夫曼树 1.什么是哈夫曼树? 2.哈夫曼树关键字说明 3.用代码实现哈夫曼树思路分析 4.代码实现 二.哈夫曼编码 1.哈夫曼编码基本介绍 2.原理剖析 3.代码实现 一.哈夫曼树 1.什 ...

  2. 【数据结构】图解霍夫曼编码,看了就能懂

    今天来给大家普及一下霍夫曼编码(Huffman Coding),一种用于无损数据压缩的熵编码算法,由美国计算机科学家大卫·霍夫曼在 1952 年提出--这么专业的解释,不用问,来自维基百科了. 说实话 ...

  3. sdut 数据结构实验之二叉树六:哈夫曼编码

    #include <iostream> #include <cstdio> #include <cstring> #include <queue>usi ...

  4. c语言递归计算哈夫曼编码,哈夫曼树遍历求WPL和哈夫曼编码C语言--For初学者

    这篇文章使用纯c来写的,实现了生成哈夫曼树.求WPL和生成哈夫曼编码的应用,思路是,先定义一个结构体如下 typedef struct node { int weight; struct node * ...

  5. 数据结构实验之二叉树六:哈夫曼编码

    Description 字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码.该方法完全依据字符出现概率来构造出平均长度最短 ...

  6. 数据结构与算法 / 霍夫曼树、霍夫曼编码和解码

    一. 诞生原因 找出存放一串字符所需的最少的二进制编码. 二. 构造方法 首先统计出每种字符出现的频率,即:概率.权值. 例如:频率表 A:60,    B:45,   C:13   D:69   E ...

  7. 【数据结构和算法笔记】哈夫曼树的概念,构造和应用(利用哈夫曼编码压缩文本)

    目录 哈夫曼树定义: 构造哈夫曼树: 哈夫曼编码 前缀编码: 应用(压缩文本) 哈夫曼树定义: 构造哈夫曼树: 哈夫曼编码 前缀编码:  哈夫曼编码是前缀编码 哈夫曼树的性质 哈夫曼树的任意非叶结点的 ...

  8. 哈夫曼编码(基于哈夫曼树-最优二叉树,不唯一)、B树(b-树)、B+树

    整合自: http://blog.csdn.net/shuangde800/article/details/7341289 http://www.cnblogs.com/Jezze/archive/2 ...

  9. 一文看懂哈夫曼树与哈夫曼编码

    转自:http://www.cnblogs.com/Jezze/archive/2011/12/23/2299884.html 在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUF ...

最新文章

  1. python整理excel数据-Python 之Excel 数据处理
  2. C语言练习题——动态数组
  3. 【Java4】实例初始化,类初始化,/接口,多态,final/static,权限修饰符/native
  4. SVD原理及其应用导论
  5. Shell脚本函数(函数传参、递归、创建库)
  6. OrderAnalyticsController.initializeCachedDB - jdbc
  7. linux下shell命令别名(alias)设置
  8. Yarn报错:error Couldn‘t publish package: “https://registry。。。 Are you logged in as the correct user?“
  9. 从51能不学编程只学c语言,51单片机C语言学习笔记8:单片机C51编程规范
  10. vs设置编码格式_轻松编辑PDF文档的贝茨编码
  11. github可以刷星吗_国内某知名社区居然也在GitHub上玩起了刷星活动
  12. Tomcat官网下载旧版本
  13. PR/AE基础入门操作
  14. 修改《植物大战僵尸》的游戏存档
  15. C语言丨整蛊必备小程序,好玩炸翻天(附源码)
  16. 服务器相关 HTTP 请求错误
  17. Python JPG图片转DCM
  18. 0.0.0.0和255.255.255.255两个特殊ip地址有什么用?
  19. 利用加速度求解位置的算法——三轴传感器
  20. Boxers CodeForces - 1203E (贪心解法)——26行代码AC

热门文章

  1. 262K Color
  2. 练习1: Python基本语法元素 (第1周)
  3. java商品展示页面代码_java学习(十四)实现商品的展示、curd以及分页展示
  4. C++(四)——类和对象(下)
  5. 关于sendinput() inserted only 0 out of 2 python程序问题的解决
  6. Linux Kernel中local_irq_enable()和local_irq_disable()的实现
  7. 密码学基础知识(六)Hash函数与消息认证
  8. 解决kubectl get pods时 No resources found.问题
  9. Android锁机样本分析
  10. 【攻防世界007】simple-check-100