文章目录

  • 引入哈夫曼树
    • 引出问题
  • 哈夫曼树的基本概念
    • 路径
    • 结点的路径长度
    • 树的路径长度
    • 权(weight)
    • 结点的带权路径长度
    • 树的带权路径长度
    • 什么是哈夫曼树
      • 注意
  • 哈夫曼树的构造算法
    • 哈夫曼算法(构造哈夫曼树的方法)
    • 例1
    • 例2
    • 总结
  • 哈夫曼构造算法的实现
    • 结点类型定义
    • 哈夫曼树构造算法的实现
  • 哈夫曼编码
    • 前缀编码
    • 引出哈夫曼编码
    • 例题
      • 两个问题
    • 哈夫曼编码的存储表示
    • 根据哈夫曼树求哈夫曼编码
    • 哈夫曼编码应用举例

引入哈夫曼树

编程:将学生的百分制成绩转换为五分制成绩。
<60:E 60-69:D 70-79:C 80-89:B 90-100:A

if(score<60)grade == 'E';
else if(score<70)grade == 'D';
else if(score<80)grade == 'C';
else if(score<90)grade == 'B';
elsegrade == 'A';


当树上带权值时:
5%的数据需1次比较,15%的数据需2次比较,40%的数据需3次比较,40%的数据需4次比较,因此10000个数据比较的次数为:
10000(1 * 5% + 2 * 15% + 3 * 40% + 4 * 10%) = 31500次
10000(3 * 20% + 2 * 80%) = 22000次

引出问题

能不能找到一种效率最高的判别树呢?
答:哈夫曼树(最优二叉树)
(判断树:用于描述分类过程的二叉树。)

哈夫曼树的基本概念

路径

从树中一个结点到另一个结点之间的分支构成这两个结点间的路径。

结点的路径长度

两结点间路径上的分支数。

(a)从A到B, C, D, E, F, G, H, I的路径长度分别为1, 1, 2, 2, 3, 3, 4, 4。

(b)从A到B, C, D, E, F, G, H, I的路径长度分别为1, 1, 2, 2, 2, 2, 3, 3。

树的路径长度

从树根到每一个结点的路径长度之和。记作TL。
TL(a) = 0+1+1+2+2+3+3+4+4=20
TL(b) = 0+1+1+2+2+2+2+3+3=16
结点数目相同的二叉树中,完全二叉树是路径长度最短的二叉树。

权(weight)

将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。

结点的带权路径长度

从根结点到该节点之间的路径长度与该结点的权的乘积。

树的带权路径长度

树中所有叶子结点的带权路径长度之和。
记作:
其中,wk为权值,lk为结点到根的路径长度。

有4个结点a, b, c, d,权值分别为7, 5, 2, 4,构造以此4个结点为叶子结点的二叉树:

带权路径长度是:
(a)WPL=7x2 + 5x2 + 2x2 + 4x2 = 36
(b)WPL=7x3 + 5x3 + 2x1 + 4x2 = 46

什么是哈夫曼树

哈夫曼树:最优树,就是带权路径长度(WPL)最短的树。
注意:“带权路径长度最短”是在“度相同”的树中比较而得的结果,因此有最优二叉树、最优三叉树之称等等。
哈夫曼树:最优二叉树,就是带权路径长度(WPL)最短的二叉树。
因为构造这种树的算法是由哈夫曼教授于1952年提出的,所以被称为哈夫曼树,相应的算法称为哈夫曼算法。

注意

满二叉树不一定是哈夫曼树。
哈夫曼树中权越大的叶子离根越近。
具有相同带权结点的哈夫曼树不唯一。

哈夫曼树的构造算法


哈夫曼树中权越大的叶子离根越近。
贪心算法:构造哈夫曼树时首先选择权值小的叶子结点。

哈夫曼算法(构造哈夫曼树的方法)

(1)根据n个给定的权值(w1, w2, …, wn)构成n棵二叉树的森林F = {T1, T2, …, Tn},其中,Ti只有一个带权为wi的根节点。
构造森林全是根
(2)在F中选取两棵根结点的权值最小的树作为左右子树,构造一棵新的二叉树,且设置新的二叉树的根结点的权值为其左右子树上根结点的权值之和。
选用两小造新树
(3)在F中删除这两棵树,同时将新得到的二叉树加入森林中。
删除两小添新人
(4)重复(2)和(3),直到森林中只有一棵树位置,这棵树即为哈夫曼树。
重复2、3剩单根

例1

有4个结点a, b, c, d,权值分别为7, 5, 2, 4,构造哈夫曼树。

例2

有5个结点a, b, c, d, e,权值分别为7, 5, 5, 2, 4,构造哈夫曼树。

总结

哈夫曼树的结点度为0或2,没有度为1的结点。
包含n棵树的森林要经过n-1次合并才能形成哈夫曼树,共产生n-1个新结点。
包含n个叶子结点的哈夫曼树中共有2n-1个结点。

在哈夫曼算法中,初始有n棵二叉树,要经过n-1次合并最终形成哈夫曼树。
经过n-1次合并产生n-1个新结点,且这n-1个新结点都是具有两个孩子的分支结点。
可见:哈夫曼树中共有n+n-1 = 2n-1个结点,且其所有的分支结点的度均不为1。

哈夫曼构造算法的实现

采用顺序存储结构——一维结构数组(HuffmanTree H;)

结点类型定义

typedef struct {int weight;int parent, lch, rch;
} HTNode, *HuffmanTree;


哈夫曼树中共有2n-1个结点,不适用0下标,数组大小为2n。
例如,第1个结点权值为5,即可表示为H[i].weight=5。

有n=8,权值为W={7, 19, 2, 6, 32, 3, 21, 10},构造哈夫曼树。

哈夫曼树构造算法的实现

1.初始化HT[1…2n-1]:lch=rch=parent=0;
2.输入初始n个叶子结点:置HT[1…n]的weight值;
3.进行以下n-1次合并,依次产生n-1个结点HT[i],i=n+1…2n-1:
(1)在HT[1…i-1]中选两个未被选过(从parent == 0的结点中选)的weight最小的两个结点HT[s1]和HT[s2], s1、s2为两个最小结点下标;
(2)修改HT[s1]和HT[s2]的parent值:HT[s1].parent=i;HT[s2].parent=i;
(3)修改新产生的HT[i]:
① HT[i].weight = HT[s1].weight + HT[s2].weight;
② HT[i].lch = s1;HT[i].rch = s2;

void CreateHuffmanTree(HuffmanTree &HT, int n)
{ //构造哈夫曼树 HTif(n<=1) return; m=2*n-l; HT=new HTNode[m+l];   //0 号单元未用,所以需要动态分配 m+l 个单元, HT[m]表示根结点for(i=1;i<=m;++i)       //将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0{HT[i].parent=O;  HT[i].lchild=O;        HT[i].rchild=O;} for(i=1;i<=n;++i}      //输人前 n 个单元中叶子结点的权值cin>>HT[i].weight;
/*- ---- ----- -初始化工作结束, 下面开始创建哈夫曼树- - - - ------ */ for (i=n+1; i<=m; ++i} {//通过 n-1 次的选择、删除 、 合并来创建哈夫曼树Select (HT, i-1, s1, s2}; //在 HT[k] (1≤k≤i-1) 中选择两个其双亲域为0 且权值最小的结点,并返回它们在 HT 中的序号 s1和 s2HT[s1].parent=i;HT[s2].parent=i; //得到新结点 i, 从森林中删除s1, s2, 将s1和s2 的双亲域由 0改为l.HT[i].lchild=s1;HT[i].rchild=s2; //s1, s2分别作为i的左右孩子HT[i].weight=HT[s1].weight+HT[s2].weight; //i的权值为左右孩子权值之和}//for
}

已知 w = (5,29,7,8,14,23,3,11), 利用算法试构造一棵哈夫曼树, 计算树的带权路径长度, 并给出其构造过程中存储结构HT的初始状态和终结状态。
n= 8, 则 m = 15, 按算法可构造一棵哈夫曼树, 如图所示。

树的带权路径长度计算如下:

其存储结构HT的初始状态如表 5.2 (a)所示, 其终结状态如表 5.2 (b)所示。

哈夫曼编码

在远程通讯中,要将待传字符转换成由二进制的字符串:
若编码为:A-00; B-01; C-10; D-11
则要传送的字符为:

若将编码设计为长度不等的二进制编码,即让待传字符串中出现次数较多的字符采用尽可能短的编码,则转换的二进制字符串便可能减少。

前缀编码


关键:要设计长度不等的编码,则必须使任一字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。

引出哈夫曼编码

问题:什么样的前缀码能使得电文总长最短?
——哈夫曼编码。

方法:
1.统计字符集中每个字符在电文中出现的平均概率(概率越大,要求编码越短)。
2.利用哈夫曼树的特点:权越大的叶子离根越近;将每个字符的概率值作为权值,构造哈夫曼树。则概率越大的结点,路径越短。
3.在哈夫曼树的每个分支上标上0或1:
结点的左分支标0,右分支标1。
把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码。

例题

要传输的字符集D = {C, A, S, T, ; }
字符出现频率w = {2, 4, 2, 3, 3 }

例:电文是{CAS;CAT;SAT;AT}
其编码是:11010111011101000011111000011000,反之,若编码是“1101000”,则其译文是“CAT”。

两个问题

1.为什么哈夫曼编码能够保证是前缀编码?
因为没有一片树叶是另一片树叶的祖先,所以每个叶结点的编码就不可能是其它叶结点编码的前缀。
2.为什么哈夫曼编码能够保证字符编码总长最短?
因为哈夫曼树的带权路径长度最短,故字符编码的总长最短。

· 性质1:哈夫曼编码是前缀编码。
· 性质2:哈夫曼编码是最优前缀编码。

哈夫曼编码的存储表示

// - - - - -哈夫曼编码表的存储表示-----
typedef char **HuffmanCode; // 动态分配数组存储哈夫曼编码表

根据哈夫曼树求哈夫曼编码

算法步骤:
1.分配存储n个字符编码的编码表空间HC,长度为n+1;分配临时存储每个字符编码的动态数组空间cd,cd[n-1]置为’\0’。
2.逐个求解n个字符的编码,循环n次,执行以下操作:
(1)设置变量start用于记录编码在cd中存放的位置,start初始时指向最后,即编码结束符位置n-1;
(2)设置变量c用于记录从叶子结点向上回溯至根结点所经过的结点下标,c初始时为当前待编码字符的下标i,f用于记录i的双亲结点的下标;
(3)从叶子结点向上回溯至根结点,求得字符i的编码,当f没有到达根结点时,循环执行以下操作:
① 回溯依次start向前指一个位置,即–start;
② 若结点c是f的左孩子,则生成代码0,否则生成代码1,生成的代码0或1保存在cd[start]中;
③ 继续向上回溯,改变c和f的值。
(4)根据数组cd的字符串长度为第i个字符编码分配空间HC[i],然后将数组cd中的编码复制到HC[i]中。
3.释放临时空间cd。

void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{   // 从叶子到根逆向求每个字符的哈夫曼编码, 存储在编码表HC中HC=new char*[n+1];     // 分配存储n个字符编码的编码表空间cd=new char[n];     // 分配临时存放每个字符编码的动态数组空间cd[n-1]='\0';      // 编码结束符for(i=1;i<=n;++i)    // 逐个字符求哈夫曼编码{start=n-1;       //start 开始时指向最后, 即编码结束符位置c=i; f=HT[i].parent;  //f指向结点c的双亲结点while(f!=O)   // 从叶子结点开始向上回溯, 直到根结点{--start;   //回溯一次start向前指一个位置if(HT[f].lchild==c) cd[start]='O';   //结点c是f的左孩子, 则生成代码0else cd[start]='1';                //结点c是f的右孩子, 则生成代码1c=f;f=HT[f].parent;                 //继续向上回溯}                                       //求出第l.个字符的编码HC[i]=new char[n-start];                  //为第i个字符编码分配空间strcpy(HC[i],&cd[start]);                 //将求得的编码从临时空间cd复制到HC的当前行中}delete cd;                                    //释放临时空间
}

哈夫曼编码应用举例

哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称“熵编码法”),用于数据的无损耗压缩。这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。这种方法是由David.A.Huffman发展起来的。 例如,在英文中,e的出现概率很高,而z的出现概率则最低。当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。若能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

数据结构-哈夫曼树详解(类C语言版)相关推荐

  1. 赫夫曼树和赫夫曼编码(C语言版)

    赫夫曼树和赫夫曼编码(C语言版) 一.赫夫曼树 (一)赫夫曼树的定义及表示方法 二.赫夫曼编码 (一)赫夫曼编码的定义及表示方法 三.C语言编写 (一)代码设计思路 1构造赫夫曼树 2在哈夫曼树上构建 ...

  2. 【赫夫曼树详解】赫夫曼树简介及java代码实现-数据结构07

    赫夫曼树(最优二叉树) 1. 简介 定义: 赫夫曼树是n个带权叶子结点构成的所有二叉树中,带权路径长度(WPL)最小的二叉树. 叶子结点的带权路径: 叶子结点权值*到根节点的路径长度(叶结点的层数) ...

  3. 《数据结构与算法》(十一)- 树、森林与二叉树的转换及哈夫曼树详解

    目录 前言 1. 树.森林与二叉树之间的转换 1.1 树转换为二叉树 1.2. 森林转换为二叉树 1.3. 二叉树转换为树 1.4 二叉树转换为森林 1.5 树与森林的遍历 2. 哈夫曼树及其应用 2 ...

  4. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  5. 数据结构哈夫曼树实现26个英文字符的编码和译码

    数据结构哈夫曼树实现26英文字符的编码和译码 那么首先什么是哈夫曼树?(知道的略过,直奔下面代码就好!) 在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编 ...

  6. C语言哈夫曼树压缩/解压器

    C语言哈夫曼树压缩/解压器 小编是大一的菜鸡,这个题目是数据结构的一个实验题,为了完成这个作业,查找了各种资料,借鉴了很多人的代码,前后折腾了三天左右.代码可能跟网上的不一样,大佬路过请不要踩我. 温 ...

  7. 数据结构--赫夫曼树

    数据结构 –赫夫曼树 文章目录 数据结构 一.一些概念 二.最优二叉树(赫夫曼树) 三.赫夫曼树的构造 四.赫夫曼编码 五.前缀编码 一.一些概念 路径:从树中一个结点到另一个结点之间的分支构成这两个 ...

  8. 数据结构---哈夫曼树

    数据结构-哈夫曼树 原理:参考趣学数据结构 代码: #include<stdio.h> #include<stdlib.h> #define N 100 #define INF ...

  9. 【数据结构——哈夫曼树及其应用】

    [数据结构--哈夫曼树及其应用] 一.哈夫曼树的基本概念 二.哈夫曼树的构造算法 (一)哈夫曼树的构造过程 (二)哈夫曼树构造算法的实现 1.初始化 2.创建树 3.完整的创建哈夫曼树代码 三.哈夫曼 ...

  10. 【DSA】树-哈弗曼树详解(3)

    什么是哈弗曼树 百度百科的定义 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长 ...

最新文章

  1. 华为机考HJ13句子逆序C语言弱智解法
  2. awk 抓取文件子集
  3. robot连接mysql_robot连接mysql - autocar - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  4. React jsx转换成原生JavaScript的一个例子
  5. 青少年python编程竞赛加分_《笨方法学Python》加分题17
  6. mysql连接自己的ip地址_mysql 连接字符串 远程连接用IP地址 而非只是localhost时
  7. 使用Excel函数时,注意函数对于大小写的区分(vlookup函数不区分大小写)
  8. paip.抓取网页内容--java php python
  9. ubuntu20.04下的录屏与视频剪辑软件
  10. klwp主题大全_klwp主题包百度网盘版下载-klwp主题包百度云版 _5577安卓网
  11. 数据挖掘实验——认识数据与进行数据预处理
  12. PHP和原生JS实现九型人格在线测试(144题)
  13. matplotlib实战(绘制电学实验中的改装表校准线)
  14. 转:深网 | 中国手机往事:因为雷军、罗永浩们,中国才告别山寨机
  15. 个人永久性免费-Excel催化剂功能第83波-遍历文件夹内文件信息特别是图像、音视频等特有信息...
  16. 新颖的基于互联网的毕业设计题目50例
  17. spyder运行时闪退解决办法:
  18. db4o官方停止支持及面向对象数据库的一些感想
  19. antdesign卡片_10分钟精通Ant Design Form表单
  20. 计算机科学与技术 研究生 缩招,2021考研招生最新信息汇总(扩招、缩招、停招、首招)...

热门文章

  1. Python 批量汉字转五笔,Word输出为Excel
  2. 暴雪战网怎么修改服务器,战网昵称修改服务
  3. PDF Expert|全能宝藏PDF编辑器
  4. java生成pdf文件并打印
  5. 凌晨3点--- 给我一支烟
  6. 错误Illegal invocation;使用jquery的ajax上传文件报错Illegal invocation
  7. 小游戏制作-其他系列-数独
  8. 华硕无线网卡测试软件,高端便携无线网卡来了 华硕USB-AC68首测
  9. 从零开始搭建ROS小车(绪论)
  10. 【机器学习】【决策树】ID3算法,Python代码实现生成决策树的系统