news 2026/6/23 10:02:48

哈夫曼编码是一种基于字符出现频率进行数据压缩的**最优前缀编码方法**

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
哈夫曼编码是一种基于字符出现频率进行数据压缩的**最优前缀编码方法**

哈夫曼编码是一种基于字符出现频率进行数据压缩的最优前缀编码方法,其核心思想是:
为高频字符分配较短的编码,为低频字符分配较长的编码,并保证任意一个字符的编码都不是其他编码的前缀(即前缀码),从而确保译码的唯一性。

一、原理与构造过程

  • 输入:一组字符及其对应的权值(通常为频率或概率)。
  • 目标:构造一棵带权路径长度最短的二叉树——哈夫曼树(Huffman Tree)
  • 构造步骤
    1. 将每个字符作为独立的结点(权值 = 频率),构成森林。
    2. 每次选出两个权值最小的根结点,合并成一个新的父结点,新结点的权值为两者之和。
    3. 重复此过程,直到只剩一棵树,即哈夫曼树。
  • 编码规则
    • 左分支标记为0,右分支标记为1
    • 从根到叶子的路径形成的二进制串即为该字符的哈夫曼编码。

示例解析

给定字符集{a, b, c, d, e},对应权值{0.30, 0.25, 0.15, 0.22, 0.08}

  1. 构造哈夫曼树后得到编码:

    • a:00
    • b:01
    • d:11
    • c:100
    • e:101
  2. 编码满足前缀性质,例如:

    • 00不是任何其他编码的前缀;
    • 可无歧义地逐位解码:如00101a,e

二、函数补全分析(生成哈夫曼编码)

voidHuffmanCoding(HuffmanTree HT,HuffmanCode HC,intn){char*cd;inti,start,c,f;if(n<=1)return;cd=(char*)malloc(n*sizeof(char));// 临时存储编码cd[n-1]='\0';// 字符串结尾for(i=1;i<=n;++i){start=n-1;// 从数组末尾向前写入编码c=i;f=HT[i].parent;// 自底向上回溯至根节点while(f!=0){if(HT[f].lchild==c)cd[--start]='0';elsecd[--start]='1';c=f;f=HT[f].parent;}// 分配空间并复制编码HC[i]=(char*)malloc((n-start)*sizeof(char));strcpy(HC[i],&cd[start]);}free(cd);// 释放临时数组}
函数逻辑说明:
  • 使用动态数组cd临时保存从叶子到根的逆向编码序列。
  • 回溯过程中根据当前节点是左孩子还是右孩子决定填'0''1'
  • 最终将反向生成的编码正向存入HC[i]中(通过指针偏移实现)。
  • 每个编码字符串独立分配内存,便于后续使用和释放。

三、结构体定义补充(常见实现)

typedefstruct{doubleweight;intlchild,rchild,parent;}HTNode,*HuffmanTree;typedefchar**HuffmanCode;// 指向字符串数组的指针
  • HuffmanTree是一个结构体数组,共2n-1个结点(n 个叶子 + n-1 个内部结点)。
  • HuffmanCode HC实际上是一个char**HC[i]指向第 i 个字符的编码字符串。

应用价值

哈夫曼编码广泛应用于无损数据压缩领域,如:

  • ZIP 压缩文件格式
  • JPEG 图像中的熵编码
  • MP3 音频压缩

它是贪心算法的经典实例:每一步选择最小权重的两棵树合并,最终获得全局最优解。

构造哈夫曼树的核心思想是贪心算法:每次选择两个权值最小的结点合并,直到所有结点合并成一棵树。这样可以保证带权路径长度(WPL)最小。


一、哈夫曼树构造算法步骤

输入:
  • 字符集对应的权值数组w[1..n],共n个叶子结点。
输出:
  • 一棵哈夫曼树(用结构体数组表示),包含2n - 1个结点。
算法步骤:
1. 初始化: - 创建 2n - 1 个结点的数组 HT。 - 前 n 个结点为叶子结点,分别赋予权值 w[i],lchild、rchild 和 parent 初始为 0。 2. 循环执行以下操作 (n - 1) 次,以构建 n - 1 个内部结点: a. 在当前所有“未被选作子树”的根结点中(即 parent == 0 的结点), 找出两个权值最小的结点,记为 m1 和 m2(m1 ≤ m2)。 b. 创建一个新的内部结点,下标为 i = n + 当前第几次合并。 c. 设置该结点的: weight = m1.weight + m2.weight lchild = m1 下标 rchild = m2 下标 parent = 0 d. 更新 m1 和 m2 的 parent 为新结点的下标。 3. 最终得到一棵哈夫曼树,根结点为 HT[2n-1]。

二、示例演示(简要)

设权值{0.30, 0.25, 0.15, 0.22, 0.08}

  1. 初始 5 个叶子:a(0.3), b(0.25), d(0.22), c(0.15), e(0.08)
  2. 合并 e(0.08) 和 c(0.15) → 新结点1 (0.23)
  3. 合并 d(0.22) 和 新结点1(0.23) → 新结点2 (0.45)
  4. 合并 a(0.3) 和 b(0.25) → 新结点3 (0.55)
  5. 合并 新结点2(0.45) 和 新结点3(0.55) → 根结点 (1.0)

最终形成哈夫曼树,根为最后一个生成的结点。


三、时间复杂度分析

方法1:使用简单遍历找最小值(适用于教学实现)
  • 每次查找最小两个元素需扫描最多O(n)个结点。
  • 共进行n - 1次合并,每次扫描O(n)
  • 总时间复杂度:O(n²)
方法2:使用优先队列(最小堆优化)
  • 将初始 n 个叶子插入最小堆:O(n)
  • 每次取出两个最小元:O(log n)
  • 插入一个合并后的新结点:O(log n)
  • 共进行n - 1次操作 →O(n log n)
  • 总时间复杂度:O(n log n)

实际应用中通常采用堆优化版本提升效率。


四、C语言伪代码(基于数组的 O(n²) 实现)

voidCreateHuffmanTree(HuffmanTree&HT,intn,doublew[]){if(n<=1)return;intm=2*n-1;HT=(HuffmanTree)malloc(m*sizeof(HTNode));// 初始化前n个叶子结点for(inti=1;i<=n;++i){HT[i].weight=w[i];HT[i].lchild=HT[i].rchild=HT[i].parent=0;}// 初始化内部结点(暂无连接)for(inti=n+1;i<=m;++i){HT[i].weight=HT[i].lchild=HT[i].rchild=HT[i].parent=0;}// 构造内部结点for(inti=n+1;i<=m;++i){intm1=0,m2=0;// 存储最小和次小的下标doublemin1=DBL_MAX,min2=DBL_MAX;// 遍历前i-1个结点,找parent==0且权值最小的两个for(intj=1;j<i;++j){if(HT[j].parent==0&&HT[j].weight<min1){min2=min1;m2=m1;min1=HT[j].weight;m1=j;}elseif(HT[j].parent==0&&HT[j].weight<min2){min2=HT[j].weight;m2=j;}}// 设置新结点HT[m1].parent=HT[m2].parent=i;HT[i].lchild=m1;HT[i].rchild=m2;HT[i].weight=min1+min2;}}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 15:12:27

YOLOv8代码审查准备:git request-pull使用

YOLOv8开发协作中的代码审查与环境标准化实践 在深度学习项目日益复杂的今天&#xff0c;一个常见的场景是&#xff1a;团队成员各自训练模型、添加新功能&#xff0c;但最终合并代码时却发现“在我机器上能跑”的问题频出——依赖版本不一致、数据预处理逻辑冲突、甚至提交记录…

作者头像 李华
网站建设 2026/6/9 19:51:55

vuespringboot基于网络环境的在线教学系统(作业考试成绩)k7p9r

目录 具体实现截图项目介绍论文大纲核心代码部分展示可定制开发之亮点部门介绍结论源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作 具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;同时还支持Python(flask,django…

作者头像 李华
网站建设 2026/6/20 6:19:40

YOLOv8 GPU显存溢出(OOM)问题排查与解决

YOLOv8 GPU显存溢出&#xff08;OOM&#xff09;问题排查与解决 在深度学习项目中&#xff0c;尤其是在使用高性能目标检测模型如 YOLOv8 时&#xff0c;开发者常常会遇到一个看似简单却极具破坏性的问题&#xff1a;GPU 显存溢出&#xff08;Out of Memory, OOM&#xff09;。…

作者头像 李华
网站建设 2026/6/10 20:35:26

华为nova15才是宠物博主本命机!清晰又还原,运动毛孩抓拍零废片

用手机给自家“毛孩子”拍照&#xff0c;最让人头疼的莫过于这两种情况&#xff1a;想抓拍它奔跑的可爱瞬间&#xff0c;结果照片一片模糊&#xff1b;或者明明它的毛发色泽鲜亮&#xff0c;拍出来却黯淡失色。如果你也有同样困扰&#xff0c;那么华为nova15系列的“风驰闪拍”…

作者头像 李华
网站建设 2026/6/20 21:34:57

YOLOv8开发者大会预告:全球技术交流盛会

YOLOv8开发者大会预告&#xff1a;全球技术交流盛会 在智能摄像头、自动驾驶和工业质检设备日益普及的今天&#xff0c;一个共同的技术挑战摆在开发者面前&#xff1a;如何在有限算力下实现高精度、低延迟的目标检测&#xff1f;答案正变得越来越清晰——YOLOv8 容器化部署。 …

作者头像 李华
网站建设 2026/6/1 6:02:25

YOLOv8插件市场构想:第三方模块自由扩展

YOLOv8插件市场构想&#xff1a;第三方模块自由扩展 在计算机视觉的战场上&#xff0c;YOLO系列早已不是“新兵”。自2015年横空出世以来&#xff0c;它凭借一次前向传播完成检测的能力&#xff0c;成了工业界实时目标检测的首选方案。而当Ultralytics推出YOLOv8时&#xff0c;…

作者头像 李华