哈弗曼树与哈弗曼编码

数据结构之哈弗曼树与哈弗曼编码 一.哈弗曼树和哈弗曼编码先知 哈弗曼树是二叉树中一种特殊的树,也被称为最优二叉树。其通过某种规则(权值)来构造出一哈夫曼二叉树,在这个二叉树中,只有叶子节点才是有效的数据节点,其他的非叶子节点是为了构造出哈夫曼而引入的! 哈夫曼编码是通过哈夫曼树进行的一种编码,一般情况下,以字符‘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万+

E28 LoRa模块透传 定点传输 RSSI测试与MicroPython应用

测试说明 测试模块数:3 测试模式:配置模式和传输模式 如果没有检测到串口,首先检查是否安装串口驱动CH341SER,下载链接,提取码:vaw2 工作模式 模式(0-3) M2 M1 M0 模式介绍 备注 0 传输模式 1 0 0 串口打开,无线打开,连续透明传输 空速支持手动配置和自适应波特率自动调节;连续模式双方波特率必须一致 1 RSSI 1 0 1 串口打开,无线打开,RSSI功能打开 模块每100ms输出RSSI强度值 2 测距模式 1 1 0 保留 - 3 配置模式

GniLAY1022的博客 4242

哈 夫 曼 树

哈夫曼树

NOSaac的博客 1万+

uniapp原生安卓插件开发之路

声明: 我的功能需求:全局悬浮框,也就是在其他应用上依旧能悬浮。查遍uni文档,无法实现,甚至native.js也无法实现,无奈只能走上原生插件开发这条不归路了。(吐槽:天天写前端js,突然写了下android简直要炸,public static String啥的,var不香嘛,不过别人严谨肯定还是有别人道理的,加油吧,争取能入个门!) 本人不懂安卓开发,完全安卓小白,所以安卓方面可能表达的不是很好,安卓代码可能写的不优美,但我功能最终还是实现了。但是为了需求,能力总能被“逼”出来。有描述错误的还望指正

Jone's Area 1万+

非目标代谢组学(untargeted metabolomics)中常用的方法学考察的方法(四)

最早使用的一种方法,从QC样本的总离子流图中选择具有代表性的离子峰(覆盖不同的保留时间,不同的强度),在对QC样本进行重复检测之后,计算这些离子的保留时间以及峰面积的相对标准偏差(RSD),用以考察分析方法的稳定性以及重复性。所有样品检测完之后,收集所有的QC样本的原始数据进行数据预处理,包括(峰提取,排列,归一化等),经过数据过滤(80%规则)之后,计算剩下的峰的峰面积的RSD值。由于QC样本是 等量混合了所有的被检测样本,理论上QC样本包含了所有样本中的代谢物,因此QC样本理论上会。

hlllllllhhhhh的博客 1487

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

假如

m0_73065213的博客 1万+

问题:dpkg-deb: error: paste subprocess was killed by signal (Broken pipe)

 1. 问题:Ubuntu安装软件的过程中出现依赖项的问题 “E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).” 按照指示执行如下两条命令都没有解决问题。 sudo apt-get -f install sudo apt-get --fix-broken ...

gloria_littlechi的博客 2万+

【数据结构】哈夫曼树

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

2301_79290137的博客 7144

因果推断综述-A Survey on Causal Inference

最近读到一篇讲述很全面的综述文献-《A Survey on Causal Inference》,对于接触因果推断不久的同学而言是特别详细的介绍和科普。文献很长,我会分成几部分介绍。 目录 摘要 第一部分:简介 第二部分:因果推断基础知识 第三部分:基于三种假设的因果推断方法 第四部分:实验 第五部分:应用 摘要 几十年来,因果推理是一个跨许多领域的关键研究主题,如统计、计算机科学、教育、公共政策和经济学。与随机对照试验相比,研究方向由于可用数据量大且预算要求低,如今,从观测数据..

海边凝望的博客 3182

多体动力学分析软件:SIMPACK_(3).SIMPACK模型创建与编辑

在 SIMPACK 中,模型的创建与编辑是多体动力学分析的基础。通过了解模型的基本结构、创建方法、编辑技巧和高级功能,用户可以高效地构建和优化复杂的多体系统模型。无论是手动创建、通过脚本创建还是导入现有的 CAD 模型,SIMPACK 都提供了强大的工具和灵活的接口,帮助用户实现精确和高效的仿真分析。希望本节内容对您在 SIMPACK 中进行多体系统建模有所帮助。如有任何问题或需要进一步的指导,请参考 SIMPACK 的官方文档或联系技术支持。

kkchenjj的博客 1010

哈夫曼树详解

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

qq_25091213的博客 1万+

手把手教你学Simulink--单相逆变器模糊逻辑控制策略仿真

本文介绍了在Simulink中设计单相逆变器模糊逻辑控制策略的完整流程。主要包括:1)构建单相逆变器模型;2)使用FuzzyLogicToolbox设计模糊控制器,定义输入输出变量和模糊规则;3)将控制器集成到Simulink模型;4)添加干扰源和示波器;5)配置仿真参数并分析结果。该方法利用模糊控制处理非线性系统的优势,可实现输出电压的精确跟踪,具有良好的鲁棒性。文中提供了详细的步骤说明和示例代码,强调准确设计隶属函数和规则库对控制性能的关键作用。该仿真设计为电力电子控制系统的开发提供了有效支持。

MHD0815的博客 200

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

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

= = 855

[网络安全自学篇] 七十三.WannaCry勒索病毒复现及分析(四)蠕虫传播机制全网源码详细解读

这是作者网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您喜欢,一起进步。前文分享了逆向分析OllyDbg动态调试工具的基本用法,包括界面介绍、常用快捷键和TraceMe案例分析。这篇文章将继续详细讲解WannaCry蠕虫的传播机制,带领大家详细阅读源代码,分享WannaCry勒索病毒是如何传播感染的。作者分析该病毒一个月,一方面觉得自己技术菜,另一方面深知系统安全需要坚持,继续加油。希望文章对您有所帮助~

杨秀璋的专栏 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

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

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

u014524107的专栏 2532

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

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

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

哈弗曼编码、哈弗曼树

哈弗曼编码是依赖于字符使用频率来建立的一种编码,通过把使用频率低的字符分配相对较多的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、付费专栏及课程。

余额充值