哈弗曼树与哈弗曼编码

数据结构之哈弗曼树与哈弗曼编码 一.哈弗曼树和哈弗曼编码先知 哈弗曼树是二叉树中一种特殊的树,也被称为最优二叉树。其通过某种规则(权值)来构造出一哈夫曼二叉树,在这个二叉树中,只有叶子节点才是有效的数据节点,其他的非叶子节点是为了构造出哈夫曼而引入的! 哈夫曼编码是通过哈夫曼树进行的一种编码,一般情况下,以字符‘0’与‘1’表示。编码的实现过程很简单,只要实现哈夫曼树,通过遍历哈夫曼树,规定向左子树遍历一个节点编码为“0”,... 阅读详情

哈弗曼,一个在几乎所有讲数据结构的书中都有出现过的人物,他的鼎鼎大名想必就不用我多说了。这一次来给大家讲解一下哈弗曼树的构建与哈弗曼编码的基本原理,有什么用呢?别急,还是先学会创建一棵哈弗曼树吧。

哈弗曼树又称最优二叉树,最优二叉树就是带权路径长度WPL最小的二叉树,那么我们就得搞清几个概念:

1.              路径长度:从树中的一个结点到另一个结点之间的分支构成这两个结点的路径,路径上的分支数目称为路径长度。

2.              树的路径长度:从树根到每一个结点的路径长度之和,我们所说的完全二叉树就是这种路径长度最短的二叉树。

3.              树的带权路径长度:如果在树的每一个叶子结点上赋上一个权值,那么树的带权路径长度就等于根结点到所有叶子结点的路径长度与叶子结点权值乘积的总和。

 

那么我们怎么判断一棵树是否为最优二叉树呢,先看看下面几棵树


 

他们的带权长度分别为:

WPL1:7*2+5*2+2*2+4*2=36

WPL2:7*3+5*3+2*1+4*2=46

WPL3:7*1+5*2+2*3+4*3=35

很明显,第三棵树的带权路径最短,这就是我们所说的最优二叉树(哈弗曼树),它的构建方法很简单,依次选取权值最小的结点放在树的底部,将最小的两个连接构成一个新结点,需要注意的是构成的新结点的权值应该等于这两个结点的权值之和,然后要把这个新结点放回我们需要构成树的结点中继续进行排序,这样构成的哈弗曼树,所有的存储有信息的结点都在叶子结点上。

下面一张图片就为大家演示了哈弗曼树的构建过程:

 

 

看了这么多,我们再来看看哈弗曼树的代码实现吧,假设我们要把一个数组中的元素封装到哈弗曼树中,那么我们需要做下面几件事:

 1.       有一个容器来存放我们的哈弗曼树的结点

 2.       有一个方法能够比较各个结点的权值大小进行排序

 3.有一个打印二叉树结点的方法(先序,中序或者后序)

 4.我们先要做一个测试用例,判断我们最后的结果是否正确

       胡zong也总是教导我们,学会分析问题远远比代码本身更重要,分析问题的同时也体现了你的逻辑思维,最开始学习编程的时候,可能更多的时候是拿到一个问题先去写,再来发现问题,但是学习了一段时间之后,更加全面的考虑问题往往比解决当前问题更重要。

       好的,不扯太远了,java的API中有一个优先队列(PriorityQueue<E>)的类,它的构造方法中有一个是可以放入一个比较器类比较队列中的元素,然后把最小的放到队列的头部,那么我们要进行一二步就变得简单了,如下:

 

Java代码  收藏代码
  1. //定义一个优先级队列来保存结点  
  2. PriorityQueue<TNode> queue=new PriorityQueue<TNode>(11,new MyComparator());  
  3. //创建一个比较器类  
  4. class MyComparator implements Comparator<TNode>{  
  5.     public int compare(TNode n1,TNode n2){  
  6.         return n1.data-n2.data;  
  7.     }  
  8. }  

打印树的结点的方法更简单:

 

Java代码  收藏代码
  1. /** 
  2.  * 先序遍历二叉树 
  3.  */  
  4. public void PreOrderTraverse(TNode root){  
  5.     if(root!=null){  
  6.         System.out.print(root.data+" ");  
  7.         PreOrderTraverse(root.lchild);  
  8.         PreOrderTraverse(root.rchild);  
  9.     }  
  10. }  

 

最后就是我们的最重要的方法了:

 

Java代码  收藏代码
  1. /** 
  2.  * 将数组中的元素封装到哈弗曼树种 
  3.  * @param arr 传入的数组元素 
  4.  * @return 哈弗曼树的根结点 
  5.  */  
  6. public TNode CreateHuffmanTree(int arr[]){  
  7.     for(int i=0;i<arr.length;i++){  
  8.     //将数组元素封装到队列当中  
  9.                  TNode node=new TNode(arr[i]);  
  10.         queue.add(node);  
  11.     }  
  12.     //如果队列的长度大于2则获取最小的两个结点  
  13.     while(queue.size()>=2){  
  14.                     TNode lnode=queue.poll();  
  15.         TNode rnode=queue.poll();  
  16.         //将元素最小的两个结点连接起来产生一个新的结点  
  17.         TNode node=new TNode(lnode.data+rnode.data);  
  18.                        node.lchild=lnode;  
  19.             node.rchild=rnode;    
  20.             queue.add(node);  
  21.     }  
  22.     //如果只剩最后一个结点,那么这个结点就是根结点  
  23.     TNode node=queue.poll();  
  24.     return node;  
  25. }  

 还有结点类:

 

Java代码  收藏代码
  1. class TNode{  
  2.     int data;//数据域  
  3.     TNode lchild,rchild;//左右孩子结点  
  4.     public TNode(int data){  
  5.         this.data=data;  
  6.     }  
  7. }  

 

讲完了这些,相信大家对于哈弗曼树也有了一定的认识,下面再简单讲解一下哈弗曼编码,至于编码的具体作用将在下次博客中提到:

构建好一颗二叉树后我们就可以对其进行编码了,编码的方式有两种:

1.       对所有的左子树路径都编码为1,右子树路径都编码为0。

2.       与第一条相反。

叶子结点的哈弗曼编码就是从根结点到该结点所经过的所有路径的编码的顺序组合。由于所经过的路径不可能重复,所以每一个叶子结点所对应的编码都是唯一的,而且,更重要的是,任意一个叶子结点的编码都不是其他叶子结点的前缀,这种编码叫做前缀编码。

如下就是一棵编码好的哈弗曼树:



    如E结点的编码就是000,C的编码就是01。。。

    好了,希望大家也能一起不断的汲取知识,软件行业,年轻的心需要更多的Energy。编程与就像体育锻炼一样,我们需要充满激情。

数据结构&&哈弗曼树和哈弗曼编码 哈弗曼树和哈弗曼编码 阅读详情

相关推荐

哈弗曼树编码完整实现(C语言项目实战)

Node;int size;// 存储指向Node的指针数组} MinHeap;

weixin_31688273的博客 1127

哈夫曼树原理解析,构造方法,意义和作用。

哈夫曼树(最优二叉树) 百度百科:https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769?fr=aladdin 一. 目的: 找出存放一串字符所需的最少的二进制编码 二. 构造方法: 首先统计出每种字符出现的频率!(也可以是概率)//权值 ----------------------------...

Anakki的博客 30万+

基于拟蒙特卡洛模拟法的随机潮流计算matlab程序

由式(4-11)可知,蒙特卡洛模拟法的计算量不受电力系统规模大小影响,因此该方法在一些复杂的电力系统中可以得到应用,包括处理电力系统中有多个间歇性新能源接入的问题,解决系统中多个节点之间相关性问题等等。本章在此基础上提出了基于拟蒙特卡洛模拟的随机潮流计算方法,并且对拟蒙特卡洛法中的拟随机数序列进行了改进,大大提高了随机潮流的计算效率。模拟法的具体思路如下:基于实际工程问题的求解需要,建立与之相对应的随机模拟过程和随机概率模型,使得它们的参数,包括概率分布或者数学期望,能够等于问题的实际解;

weixin_47365903的博客 1792

哈 夫 曼 树

哈夫曼树

NOSaac的博客 1万+

Blender关于GIS安装及使用天地图

Blender下载安装及GIS插件的安装及使用

Miss_SQ的博客 6968

流媒体弱网优化之路(NACK)——纯NACK方案的优化探索

流媒体学习之路(NACK)——纯NACK方案的最高性能 文章目录流媒体学习之路(NACK)——纯NACK方案的最高性能一、NACK简介二、Nack的理解2.1 一种补救策略2.2 什么时候要?2.3 要多少?2.4 怎么要?三、计算分析3.1 rtt强相关3.2 补包次数计算3.3 Nack的定时发送3.4 nack重传限制四、实验   近期在针对纯丢包场景做一些简单的探索实验,一个让我困扰的问题就是:不使用FEC而只是通过纯NACK进行补偿,到底能在实验环境下抵抗多少的丢包呢?每一次丢包补偿的最大时长

qw225967的博客 1万+

哈夫曼树(Huffman)【数据结构】

假如

m0_73065213的博客 1万+

MPN – 制造商物料编号(延伸)

此外,用户还可以在物料主数据中定义阻止MPN材料的原因,以及在采购订单创建时,是否可以将现有的MPN材料修改为其他MPN材料,从而实现对MPN材料的精细控制和管理。通过使用AMPL,用户可以指定每个MPN材料是否仅能为特定工厂或整个企业所有工厂采购、采购的时间段、是否必须属于特定修订级别、是否只能从特定制造商工厂采购以及是否被阻止及其原因。通过AMPL管理,企业可以规范采购流程,避免使用未经批准的材料,从而提高采购的透明度和效率,同时也为质量控制提供了保障‌。3、QM中的制造商物料。质量信息记录QI01。

yanzibing99的博客 2484

【数据结构】哈夫曼树

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

2301_79290137的博客 7144

告别迷茫!用ETAS RTA-OS配置你的第一个AUTOSAR OS任务(含VRTA虚拟ECU实战)

本文详细介绍了如何使用ETAS RTA-OS工具链在VRTA虚拟ECU上配置和运行第一个AUTOSAR OS任务。通过从XML配置到任务调度的全流程实战,帮助开发者快速掌握嵌入式操作系统开发的核心步骤,特别适合刚接触AUTOSAR的开发者快速上手。

weixin_42533622的博客 418

Hexo博客使用PDF.js

clone了一个pdf.js 然后兴高采烈地到文章里使用{% pdf %}标签 结果浏览器弹出了个下载框(使用GitHub的raw) 不知道是不是因为使用GitHub的原因导致这个问题 后来我测试的时候报了个错 优快云上的解决方法 到时候我再试试把资源放回lib/里面看看行不行 目录1.clone1.1.官方方法1.2.NexT主题方法1.3.补充2.修改文件2.1.修改viewer.htm...

LTFan 961

哈夫曼树详解

一、哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树。 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树。 这个定义里面涉及到了几个陌生的概念,下面就是一颗哈夫曼树,我们来看图解答。 (1) 路径和路径长度 定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的...

qq_25091213的博客 1万+

二、TCP/IP协议之网络层(IP地址的格式、分类、报文格式)

数据报每经过一个路由器,路由器都要重新计算一下首部检验和,若首部未发生变化,则此结果必为 0,于是就保留这个数据报。对于网络号相的设备,无论实际所处的物理位置如何,它们都是处在同一个网络中。在首部的固定部分的后面是一些可选字段,其长度是可变的。IPv4 软件在存储器中维持一个计数器,每产生一个数据报,计数器就加 1,并将此值赋给标识字段。表示数据报在网络中的寿命,英文缩写是 TTL(Time To Live),功能是“跳数限制”。地址的网络号码字段用来标识一个网络,网络号码字段的前几位用来区分。

锦慈的技术博客 184

哈弗曼树与哈弗曼编码(实现)

哈弗曼树与哈弗曼编码 历史背景 1951年,霍夫曼在MIT攻读博士学位,他和修读信息论课程的同学得选择是完成学期报告还是期末考试。导师Robert Fano出的学期报告题目是:查找最有效的二进制编码。由于无法证明哪个已有编码是最有效的,霍夫曼放弃对已有编码的研究,转向新的探索,最终发现了基于有序频率二叉树编码的想法,并很快证明了这个方法是最有效的。使用自底向上的方法构建二叉树避免了次优算法香农-范...

= = 855

OpenClaw 钉钉和飞书集成方案研究 & OpenClaw 研究分析报告

OpenClaw(原名 Clawdbot,曾用名 Moltbot)是一款开源的个人 AI 智能体,采用"本地优先"设计理念。与传统聊天机器人不同,OpenClaw 具备真正的系统级执行能力,能够实际操作用户的计算机系统,完成各种实际任务。核心优势本地部署:所有数据存储在用户本地设备,隐私零泄露系统级执行:具备完整的系统访问权限,可执行文件操作、命令运行等全渠道交互:支持多种即时通讯平台作为交互界面开源透明:MIT 许可证,代码完全开放,社区驱动开发应用场景个人助理:日程管理、任务提醒、邮件处理。

AI天才研究院 2340

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

哈弗曼树的创建编码及译码

哈弗曼树创建并实现编码译码采用C语言实现从文件读取数据,构造创建哈弗曼树,实现编码译码过程。

u014524107的专栏 2532

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++ 哈弗曼树类 创建哈弗曼树、输出哈弗曼树、输出哈弗曼编码

#include <stdlib.h> #include <iostream> int *findMin(struct TreeNode *trees,int length); using namespace std; struct huffmanCode{ int *p; int start; }; struct TreeNode{ int wight; int...

一个懒惰的程序员 512

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

哈弗曼编码、哈弗曼树

哈弗曼编码是依赖于字符使用频率来建立的一种编码,通过把使用频率低的字符分配相对较多的01编码,而使用频率高的分配相对较低的01编码,来建立最小的带权路径长度的树,来最大化的获得编码存储空间的一种编码规则。这个树称为哈弗曼树,也称为最优二叉树。 这样可以确定每一个字符的编码不可能成为其他字符编码的坐子串,也就是当读到某一个根节点时,就可以确定这个字符已经读完了;下一个字符的编码要重新读入。原因是经过...

H4ppyD0g的博客 432

用哈弗曼树对输入的字符串进行编码

结果为: 缺陷:对英文单引号不支持 //构造哈夫曼树和哈夫曼编码的算法实现 //统计下面一段英文的不同字符个数和每个字符的出现频率,利用统计数据构造构造哈夫曼树和哈夫曼编码 #include <iostream> #include<string> #include <map> using namespace std; map<char, int>...

vancece 1825

哈弗曼树的创建及哈弗曼编码

今天晚上花了好几个小时写了这个程序。。。都怪我效率太低。。。好了废话不多说,下面就给出我的代码。(这个代码参考了 严蔚敏老师 的算法)其中具体的实现就不多讲,因为我在注释都写了。 #includeusing namespace std;struct hTNode{ unsigned int weight; unsigned int parent,lchild,rchild;

凌云壮志 1267

哈弗曼树的建立与编码

哈弗曼树问题:在"7.in"中有几个数,和为1,进行哈弗曼编码,并把编码结果输出到"7.out"中。 Sample input: 0.1 0.15 0.2 0.25 0.3 Sample output: 000 001 01 10 11 思路: 根据哈夫曼树的建立思想,每一次都是选取权重最小的两个子树进行合并成新的树,然后再将新树加入到集合中,直至集合中只有最后一颗树。 这个集合可以考虑使用优先队列来进行保存子树集合,这样我们可以不用考虑选取最小的两个子树的过程,优先队列会直接返回权值最小的子树。 关

目标:NLP算法工程师 286

哈弗曼树建立与哈弗曼编码

#include&lt;iostream&gt; #define LEN sizeof(HaffmanNode) #define MAXSIZE 100 #define MAX 9999 using namespace std; typedef struct{ int value; int lChild,rChild,parent; }HaffmanNode,H...

Jay Chang 200
上一篇: 架构师成长历程:时刻对新技术保持敏感
下一篇: 哈弗曼压缩与解压的原理及对象化实现
wangshfa
博客等级 码龄17年 117粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值