首页 > 其他分享 >哈夫曼编码

哈夫曼编码

时间:2024-10-29 22:16:38浏览次数:6  
标签:编码 哈夫曼 队列 最小 freq 节点

哈夫曼编码

文章目录

引入

一个文件的内容信息可以用二级制字符编码的方式来表示,即每个字符用唯一的二进制串来表示,称为码字。

定长编码:每个字符用相同长度的二进制位数唯一表示。

e.g.一个含有10万个字符的文件,仅出现a-f这7个不同的字符,下表为对应出现次数和编码,000表示a,001表示b….

abcdefg
出现次数(千次)4020158764
定长编码000001010011100101111
变长编码01101111000100110101011

根据定长编码可以计算出需要(40+15+20+8+7+6+4)*1000*3=300 000个二进制位数来编码文件。

根据变长编码可以计算出需要(40*1+20*3+15*3+8*4+7*4+6*4+4*4)*1000=245 000个二进制位数来编码。

节约了约18%的空间。

可以看出,出现次数越多的字符编码越短,出现次数越少的字符编码越长,从而实现压缩空间.

哈夫曼树

我们可以构造一个二叉树来表示定长编码和变长编码及其对应的字符。叶节点为字符,其根节点到叶节点的简单路径为码字,其中0表示向左,1表示向右

请添加图片描述

文件的最优编码方案编码方案对应一颗满二叉树,即每个非叶子节点只有两个孩子节点。若有C个叶节点,则有C-1个内部节点。

代价

对于字母表C中的任意一个字符c,设c.freq为c出现的频率,令dT©表示c在树中的深度,同时dT©也等价于对应需要的编码长度。则总代价为
∑ c 属于 C n c . f r e q ∗ d T ( c ) \sum_{c属于C}^{n} c.freq*d_T(c) c属于C∑n​c.freq∗dT​(c)

构造哈夫曼编码

哈夫曼算法通过贪心算法来构造哈夫曼树。给定一个有n个字符及其频率的集合,每次合并频率最小的两个节点,新节点的频率等于合并的两个节点的频率之和,重复执行n-1次。使用频率freq为关键字的最小优先队列Q,以方便找到频率最小的两个节点。

ps:以freq为关键字的最小优先队列,总是满足队列头部的元素的freq最小,且队列元素按freq递增排列。由于队列是先进先出,队列弹出总是先弹出队列的头部。

先伪代码表示大概流程:

C为含有n个节点的结构体数组,c.freq为频率,Q为以频率freq为关键字的最小优先队列,EXTRACT-MIN( )每次弹出最小优先队列最小的节点,INSERT( )将元素插入队列且保持Q仍然为最小优先队列。

HUFFMAN(C){
   n=|C| //n为节点个数
   for i=1 to n//将节点加入最小优先队列中
   Q=INSERT(C[i])
   
   for i=1 to n-1
       TreeNode* z;//新建一个节点作为频率最小的俩个节点的父节点
       z.left=EXTRACT-MIN(Q)
       z.right=EXTRACT-MIN(Q)
       z.freq=z.left.freq + z.right.freq //新节点的频率为最小的两个节点的频率和
       INSERT(Q,z)//将新节点插回最小优先队列中
   return EXTRACT-MIN(Q)//此时队列中只剩下一个节点,即哈夫曼树的根节点
}

流程图:

请添加图片描述

这里出现编码与开篇的变长编码不同,原因可能是左右孩子不同,或者出现频率相同的节点的合并的先后不同,共同导致的两次哈夫曼编码不同,但代价是相同的。第一次已经计算过了为245 000,第二次为(40*1+(20+15)*3+(4+6+7+8)*4)*1000=245 000,代价相同。

最小优先队列用最小二叉堆实现,则每次堆操作的时间复杂度为O(lg n),循环了n-1次,所以循环部分时间复杂度为O(n lgn),加上初始化花费时间O(n),总共需要O(n + n lg n)=O(n lg n)。

代码:

晚点吧...

O(n lgn),加上初始化花费时间O(n),总共需要O(n + n lg n)=O(n lg n)。

代码:

晚点吧...

标签:编码,哈夫曼,队列,最小,freq,节点
From: https://blog.csdn.net/2301_80489164/article/details/143351126

相关文章

  • 数据结构 之 哈夫曼树及其应用(八)
    提示:本节重点是哈夫曼树的构造文章目录哈夫曼树的基本概念举例※构造哈夫曼树基本思想※构造哈夫曼树过程哈夫曼树的应用1------用于最佳判断过程哈夫曼树应用2----用于通信编码哈夫曼编码总结哈夫曼树的基本概念路径长度:由树中一个结点到另一结点的分支构成这......
  • 成为不可取代的程序员的编码方式
    背景在一家公司呆了两年了,作为工作十多年的程序员来说,真心感觉这两年时间是真的长,每天上班如上坟,度日如年。21年入坑,接手了一个老项目,进去后发现项目几乎天天报错,每天群里bug满天飞,每天改完一个bug,一会群里又开始叫,每天都是晚上下班才有时间输出业务代码。开始还特别不习......
  • 独热编码Python实现
    test_dataseasonmonth1112132425263738394104114121-4代表4个季节;1-12代表12个月。importpandasaspddata_path='test_dada.csv'#读取数据到内存data=pd.read_csv(data_path)dummy_fields=['season','month']#所有类型编码变量的名称foreach......
  • Python编码规范
        为什么不直接进入Python的语法和数据类型阶段,而是介绍Python编码规范?因为这很重要!作为一个开发的老鸟,给新人的第一个建议就是Python编码规范,这种规范很多时候不仅仅是Python,祝大家养成良好的代码习惯!~~~~一.忽略代码规范的规则以下情况可以忽略代码规范,其余情况请尽量......
  • 【笔记】LLM位置编码之标准位置编码
    标准位置编码起源原理证明:对于任何固定的偏移量kkk,P......
  • 实战篇:(二十一)Java 开发指南:避免 18个常见错误,提升你的编码效率
    实战篇:(二十一)Java开发指南:避免18个常见错误,提升你的编码效率Java作为一门成熟的编程语言,拥有丰富的生态系统与广泛的应用。然而,即使是经验丰富的开发者,也时常会在日常开发中犯一些常见的错误。这些错误不仅会影响代码的可读性,还可能造成性能问题甚至难以调试的Bug。本......
  • 前端摸小子,教你减少无意义的编码
     在高效摸鱼的同时,我一直在思考:有没有办法用几个简单的单词缩写,就能快速输出想要的代码呢?    答案是肯定的!接下来,我将向大家介绍前端程序员必备的两大摸鱼小技巧:   一、vscode自定义代码片段位置step1按下Ctrl+Shift+P(Mac上是Cmd+Shift+P),输入"snippet......
  • 为什么在http协议中使用base64编码方式传输二进制文件
    相关:图解Base64实现原理并使用js实现一个简单的Base64编码器常用加密方法之Base64编解码及代码实现一直都知道在http协议中使用base64的方式传递二进制文件,虽然感觉不理解,但是也都从来没有探究过原因,今天突然看到这方面的资料,这才有了一些理解。PS:把带有图片的网页......
  • 无监督的神经网络模型——自动编码器(Autoencoder)解读
    采用自动编码器进行高效特征提取详解自动编码器(Autoencoder)是一种无监督的神经网络模型,广泛应用于数据降维、特征提取、数据压缩和去噪等领域。通过学习数据的有效编码,自动编码器能够将高维数据映射到低维隐含空间,同时保留尽可能多的原始信息。本文将深入探讨如何采用自动......
  • Python 自编码器(Autoencoder)算法详解与应用案例
    目录Python自编码器(Autoencoder)算法详解与应用案例引言一、自编码器的基本原理1.1自编码器的结构1.2自编码器的类型二、Python中自编码器的面向对象实现2.1`Autoencoder`类的实现2.2`Trainer`类的实现2.3`DataLoader`类的实现三、案例分析3.1手写数字去噪自......