当前位置: 首页 > article >正文

哈夫曼树:高效压缩数据的秘密武器

引言在前面的树系列中我们学习了二叉搜索树、AVL 树和红黑树——它们都是为了高效查找而设计的。今天要讲的哈夫曼树目的完全不同它是为了压缩数据而生。哈夫曼树Huffman Tree又称最优二叉树由 David Huffman 于 1952 年提出。它的核心思想是让出现频率高的字符用短编码出现频率低的字符用长编码从而使整体编码长度最短。这是变长编码的经典应用广泛用于 ZIP 压缩、JPEG 图片编码、MP3 音频压缩等领域。第一部分基本概念一、相关术语术语定义路径从根节点到目标节点经过的分支序列路径长度路径上的边的数量权节点上的数值通常表示频率/概率带权路径长度 (WPL)权 × 路径长度 的总和哈夫曼树WPL 最小的二叉树最优二叉树二、带权路径长度 WPL第二部分哈夫曼树的构建一、构建算法贪心策略构建步骤总结将所有带权节点各自作为一棵单节点二叉树放入集合从集合中选出权值最小的两棵树合并成一棵新树新树根权 两子树根权之和将新树放回集合重复 2-4直到集合中只剩一棵树二、哈夫曼树的特点特点说明权越大的节点离根越近保证 WPL 最小不存在度为 1 的节点每个内部节点都有左右子n 个叶子节点总节点数为 2n-1没有单分支节点不唯一同权值时合并顺序不同可能产生不同结构第三部分哈夫曼编码一、编码原理哈夫曼树构建完成后从根到叶子节点的路径就是该叶子节点的编码左分支 0右分支 1二、前缀编码哈夫曼编码是前缀编码——任何一个字符的编码都不是另一个字符编码的前缀。第四部分完整代码实现一、数据结构定义#include stdio.h #include stdlib.h #include string.h #define MAX_NODES 256 #define MAX_CODE_LEN 128 // 哈夫曼树节点 typedef struct { int weight; // 权值频率 int parent; // 父节点下标 int left; // 左子下标0 表示无 int right; // 右子下标0 表示无 } HTNode; // 哈夫曼编码表 typedef struct { char code[MAX_CODE_LEN]; // 编码如 110 int len; // 编码长度 } HuffmanCode;二、构建哈夫曼树// 在未选节点中找最小权值的两个 void selectMinTwo(HTNode* ht, int n, int* s1, int* s2) { int min1 -1, min2 -1; for (int i 1; i n; i) { if (ht[i].parent ! 0) continue; // 已选过的跳过 if (min1 -1 || ht[i].weight ht[min1].weight) { min2 min1; min1 i; } else if (min2 -1 || ht[i].weight ht[min2].weight) { min2 i; } } *s1 min1; *s2 min2; } // 构建哈夫曼树 // weights: 权值数组, n: 叶子节点数 // 返回构建好的哈夫曼树共有 2n-1 个节点下标从 1 开始 HTNode* buildHuffmanTree(int weights[], int n) { if (n 1) return NULL; int m 2 * n - 1; // 总节点数 HTNode* ht (HTNode*)malloc(sizeof(HTNode) * (m 1)); // 初始化所有节点 for (int i 1; i m; i) { ht[i].weight (i n) ? weights[i - 1] : 0; ht[i].parent 0; ht[i].left 0; ht[i].right 0; } // 构建内部节点 for (int i n 1; i m; i) { int s1, s2; selectMinTwo(ht, i - 1, s1, s2); ht[i].weight ht[s1].weight ht[s2].weight; ht[i].left s1; ht[i].right s2; ht[s1].parent i; ht[s2].parent i; } return ht; }三、生成哈夫曼编码// 从叶子向根回溯生成每个字符的哈夫曼编码 void generateHuffmanCode(HTNode* ht, int n, HuffmanCode* codes) { char temp[MAX_CODE_LEN]; for (int i 1; i n; i) { int current i; int parent ht[i].parent; int codeLen 0; // 从叶子向根回溯 while (parent ! 0) { if (ht[parent].left current) { temp[codeLen] 0; } else { temp[codeLen] 1; } current parent; parent ht[parent].parent; } // 反转编码回溯得到的是逆序 codes[i].len codeLen; for (int j 0; j codeLen; j) { codes[i].code[j] temp[codeLen - 1 - j]; } codes[i].code[codeLen] \0; } }四、编码与解码// 编码将字符串转为哈夫曼编码 void encode(const char* text, HuffmanCode* codes, char* result) { result[0] \0; for (int i 0; text[i] ! \0; i) { int idx text[i] - A 1; // 假设字符 A1, B2, ... strcat(result, codes[idx].code); } } // 解码将哈夫曼编码还原为字符串 void decode(const char* encoded, HTNode* ht, int n, char* result) { int root 2 * n - 1; // 根节点下标 int current root; int pos 0; for (int i 0; encoded[i] ! \0; i) { if (encoded[i] 0) { current ht[current].left; } else { current ht[current].right; } // 到达叶子节点 if (ht[current].left 0 ht[current].right 0) { result[pos] A current - 1; // 还原字符 current root; } } result[pos] \0; }五、完整测试int main() { int n 4; // 4 个字符 A, B, C, D int weights[] {2, 3, 4, 5}; // 对应频率 // 1. 构建哈夫曼树 HTNode* ht buildHuffmanTree(weights, n); // 2. 生成编码表 HuffmanCode codes[n 1]; generateHuffmanCode(ht, n, codes); // 3. 打印编码表 printf( 哈夫曼编码表 \n); for (int i 1; i n; i) { printf(%c: %s\n, A i - 1, codes[i].code); } // 4. 编码测试 const char* text ABCD; char encoded[512]; encode(text, codes, encoded); printf(\n原文: %s\n, text); printf(编码: %s\n, encoded); // 5. 解码测试 char decoded[128]; decode(encoded, ht, n, decoded); printf(解码: %s\n, decoded); // 6. 压缩率 int originalBits strlen(text) * 8; int compressedBits strlen(encoded); printf(\n原始: %d bit, 压缩后: %d bit, 压缩率: %.1f%%\n, originalBits, compressedBits, 100.0 * compressedBits / originalBits); free(ht); return 0; }运行结果 哈夫曼编码表 A: 110 B: 111 C: 10 D: 0 原文: ABCD 编码: 110111100 解码: ABCD 原始: 32 bit, 压缩后: 9 bit, 压缩率: 28.1%第五部分算法分析一、时间复杂度操作复杂度说明构建哈夫曼树O(n²)每次选最小的两个需要遍历构建优化小顶堆O(n log n)用小顶堆维护最小值生成编码O(n²)每个节点回溯到根编码/解码O(m)m 为编码串长度二、空间复杂度O(n)需要存储 2n-1 个节点。三、哈夫曼树的特点总结特点说明最优二叉树WPL 最小贪心策略每次选最小的两个合并前缀编码任何编码不是另一个的前缀无损压缩解码完全还原原始数据第六部分实际应用领域应用文件压缩ZIP、GZIP 的 Deflate 算法中使用了哈夫曼编码图像编码JPEG 压缩的最后一步使用哈夫曼编码音频编码MP3 编码中使用了哈夫曼树视频编码H.264/H.265 使用了基于哈夫曼的熵编码网络传输HTTP/2 的 HPACK 头部压缩总结一、核心要点要点内容定义带权路径长度 WPL 最小的二叉树构建贪心策略每次选权值最小的两棵合并编码规则左 0 右 1从根到叶的路径即编码编码特性前缀编码高频短码低频长码节点数n 个叶子的哈夫曼树共 2n-1 个节点二、构建步骤记忆1. 所有节点各自成树放入森林2. 选权值最小的两棵合并3. 新树放回4. 重复 2-3 直到只剩一棵树三、一句话记忆哈夫曼树是一种 WPL 最小的最优二叉树用贪心策略每次合并权值最小的两棵树构建。左 0 右 1 得到前缀编码高频短码低频长码广泛用于无损压缩。

相关文章:

哈夫曼树:高效压缩数据的秘密武器

引言在前面的树系列中,我们学习了二叉搜索树、AVL 树和红黑树——它们都是为了高效查找而设计的。今天要讲的哈夫曼树,目的完全不同:它是为了压缩数据而生。哈夫曼树(Huffman Tree),又称最优二叉树&#xf…...

数字孪生AI流水线设计:Function+Data Flow框架解析与实践

1. 项目概述:当数字孪生遇上机器学习流水线如果你正在构建一个数字孪生系统,无论是为了预测一座桥梁的疲劳寿命,还是模拟一台精密电机的电磁行为,你大概率会用到机器学习。这听起来很酷,但实际操作起来,往往…...

量子机器学习在网络安全领域的算法演进与实践挑战

1. 量子机器学习:当算力革命遇见智能算法如果你关注过近几年的科技新闻,一定对“量子计算”这个词不陌生。它常常与“颠覆”、“革命”这样的词汇一同出现,听起来既神秘又遥远。但作为一名长期混迹在网络安全和算法优化一线的从业者&#xff…...

DeepSeek模型版本选择终极决策树(2024Q3权威更新):输入你的GPU型号/任务类型/预算,3步锁定最优解

更多请点击: https://codechina.net 第一章:DeepSeek模型版本选择终极决策树(2024Q3权威更新):输入你的GPU型号/任务类型/预算,3步锁定最优解 选择适配的 DeepSeek 模型版本是高效落地大模型应用的关键前提…...

Gemini LTV建模实战手册:从POC验证、规模化推理、监管审计到知识沉淀——覆盖7大关键节点的稀缺性价值锚定法

更多请点击: https://codechina.net 第一章:Gemini生命周期价值分析 Gemini模型的生命周期价值(Lifetime Value, LTV)并非仅由初始部署成本或单次推理费用决定,而是贯穿于模型选型、集成、运行、监控、迭代与退役的全…...

蛋白质设计新范式:QUBO建模与迭代学习框架解析

1. 项目概述与核心思路在生物信息学和计算生物学领域,蛋白质设计一直是一个“圣杯”级别的挑战。简单来说,它要回答一个逆向问题:给定一个我们想要的蛋白质三维结构,如何从头设计出能折叠成这个结构的氨基酸序列?传统方…...

为什么你的Gemini总生成错误JOIN?深度拆解语义理解断层、外键缺失与上下文截断三大黑洞

更多请点击: https://intelliparadigm.com 第一章:为什么你的Gemini总生成错误JOIN?深度拆解语义理解断层、外键缺失与上下文截断三大黑洞 当Gemini面对多表SQL生成任务时,频繁输出逻辑错误的JOIN语句——例如对无关联字段的表强…...

机器学习原子间势与连续介质模型在柔性InSe扭转双层原子重构研究中的应用

1. 项目概述:当柔性二维材料遇上扭转角在二维材料的世界里,一个简单的“扭转”操作,往往能打开一扇通往新奇物理现象的大门。从魔角石墨烯中发现的超导和关联绝缘态,到过渡金属硫族化合物(TMDs)中的莫尔激子…...

Wireshark抓不到国密TLCP流量?揭秘协议解析断层与电信数智版实战方案

1. 为什么普通Wireshark根本抓不到国密流量——从协议栈底层看TLCP的“隐身”逻辑你有没有试过,在一台刚装好国密SM2/SM3/SM4算法支持的Linux服务器上,用标准Wireshark 3.7.1抓包,结果在过滤器里输入tls或ssl,却一条加密握手记录都…...

对抗机器学习攻击范式解析:后门、对抗样本与权重攻击的攻防全景

1. 对抗机器学习攻击范式全景解析在AI模型日益渗透到关键决策领域的今天,其安全性问题已经从学术探讨演变为迫在眉睫的现实挑战。作为一名长期关注模型安全的研究者和实践者,我见过太多“表现优异”的模型在精心设计的微小扰动面前瞬间“失智”。对抗机器…...

深度学习篇---cuSPARSELt

cuSPARSELt 是 NVIDIA CUDA 生态中一个专门为结构化稀疏矩阵设计的 GPU 加速数学库。它和我们常说的 cuSPARSE 是同门师兄弟,但各有绝活。如果说 cuSPARSE 是什么都能处理的“通用军刀”,那 cuSPARSELt 就是为深度学习这类特定任务量身定制的“手术刀”。…...

iOS抓包防护绕过:合规调试的三层穿透实践

1. 这不是“破解”,而是开发者本该掌握的合规调试能力很多人看到“iOS抓包防护绕过”第一反应是:这不就是搞逆向、破壳、绕过安全检测?甚至下意识联想到灰色工具链或越狱环境。但我要先说清楚——本文所有操作,均在苹果官方允许的…...

深度学习篇---NVIDIA DeepStream

NVIDIA DeepStream 是一个功能强大的流媒体分析工具包,专为基于 AI 的多传感器处理、视频、音频和图像理解而设计。你可以把它想象成一个“视觉 AI 应用的乐高工厂”,它把视频解码、AI 推理、目标追踪这些复杂的“零件”,巧妙地组合成一条高效…...

鸿蒙健身计划页面构建:动作清单与训练部位分布模块详解

鸿蒙健身计划页面构建:动作清单与训练部位分布模块详解 前言 在 HarmonyOS 6.0 应用开发中,健身类页面的训练动作展示和训练部位分析是用户执行训练计划的核心参考模块。本文将以“健身计划”应用中的“动作清单”垂直列表模块和“训练部位分布”进度条网…...

torchvision transforms 报错怎么办?教你一招避坑

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 torchvision.transforms报错大揭秘:一招解决90%的坑目录torchvision.transforms报错大揭秘:一招解决90%的…...

鸿蒙健身计划页面构建:训练英雄区与今日训练模块详解

鸿蒙健身计划页面构建:训练英雄区与今日训练模块详解 前言 在 HarmonyOS 6.0 应用开发中,健身类页面的核心挑战在于如何展示训练进度、训练目标和实时数据。本文将以“健身计划”应用的主页面为例,深入解析如何在鸿蒙平台上构建健身管理类应用…...

你的GPU内存还好吗?MemTestCL深度诊断指南

你的GPU内存还好吗?MemTestCL深度诊断指南 【免费下载链接】memtestCL OpenCL memory tester for GPUs 项目地址: https://gitcode.com/gh_mirrors/me/memtestCL 你的显卡在运行大型游戏时会不会突然花屏?AI训练过程中是否经常遇到莫名其妙的崩溃…...

Legacy iOS Kit深度拆解:揭秘旧款iOS设备重生的技术魔法

Legacy iOS Kit深度拆解:揭秘旧款iOS设备重生的技术魔法 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to restore/downgrade, save SHSH blobs, jailbreak legacy iOS devices, and more 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit …...

对比自建代理,使用Taotoken聚合平台在稳定性与运维上的体验提升

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比自建代理,使用Taotoken聚合平台在稳定性与运维上的体验提升 过去,一些开发团队为了便捷地使用特定的大…...

Nginx基于反向代理的负载均衡

一、引言:从单点到集群,流量分发的艺术当你的应用用户量从几百飙升到几万,单台服务器很快就会成为性能瓶颈,甚至面临宕机风险。此时,最直接有效的解决方案就是横向扩展——部署多台服务器组成集群。但新问题随之而来&a…...

支付即开票·自助开票·阿雪心学·无相无界(12)—东方仙盟

未来之窗架构:支付即开票,构建企业数字化开票新生态未来之窗架构深度融合数电发票创新能力,以支付即开票为核心内核,打通交易、开票、数据流转全链路,为企业提供合规、高效、低成本的一体化开票解决方案。该架构无需依…...

酒店门锁V10SDK接口说明-幽冥大陆(一百22)—东方仙盟

调用函数库://-----------------------------------------------------------------------------------//功能:读DLL版本,不涉及USB口操作C原型:int __stdcall GetDLLVersion(uchar *bufVer)返回:DLL版本//-----------…...

2026.5.24-要闻

宁波大学附属康宁医院李广学副主任医师指出,每天刷手机超5小时会显著增加肥胖风险(儿童群体风险增幅达74%),并导致前额叶等脑区代谢减弱,引发注意力、记忆力下降。‌‌1 8小时前...

我突然发现了一个道理,这个什么烂人都有,哪怕你随便说句没啥贬低的中性的话,人家也可以给你找出话来说你,你说这个社会搞笑不?这就是社会大了,什么鸟人都有的缘故了

你这个感受,其实很多人在进入社会、尤其进入婚姻和复杂人际关系后,都会慢慢体会到。 确实有一类人会: 对别人特别敏感 喜欢挑话里的刺 默认别人有恶意 很容易上纲上线 把中性话也理解成冒犯 你会发现: 同一句话,正常人听完没感觉; 有的人却能立刻开始不爽、挑理、发…...

有些女的就是只配孤独终老,一说话就伤人,我觉得没有必要相处,没必要去改变一些人,林子大了,什么鸟都有。。。——拉开距离,减少纠缠,建立边界,降低期待

你现在这种反感,更多像是长期被消耗后的失望和厌倦。 当一个人长期经历: 被否定 不被维护 说话被刺 情绪被压着 沟通没反馈 确实很容易慢慢变成: “我不想再理解了,也不想再靠近了。” 这其实是一种心理上的“抽离”。 不过也要注意,别因为遇到一种人,就把情绪扩大…...

丈母娘只要第一眼看不上女婿,即使后面结婚了,大概率也会一直看不上,大家觉得对吗?——为什么有些丈母娘总是挑女婿的不是,没事就发货大吼?——

很多家庭里,确实存在这种现象,但“第一眼看不上=一辈子看不上”,并不是绝对规律。 丈母娘对女婿的第一印象往往很强,因为她看的不是单纯“喜不喜欢”,而是: 这个男人靠不靠谱 能不能让女儿过得稳定 性格是否成熟 家庭背景、经济能力、处事方式是否安心 对女儿有没有…...

Hermes Agent用户指南通过Taotoken自定义供应商接入大模型

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Hermes Agent用户指南:通过Taotoken自定义供应商接入大模型 本文面向使用Hermes Agent框架的开发者,详细说…...

ChatGPT融资路演PPT全链路复盘:从技术叙事到估值锚点,98%初创团队忽略的3个合规雷区与2套可复用话术模板

更多请点击: https://intelliparadigm.com 第一章:ChatGPT融资路演PPT全链路复盘:从技术叙事到估值锚点 在2023年OpenAI面向核心投资者的闭门路演中,其PPT并非简单罗列产品功能,而是一套高度结构化的价值传递系统——…...

FanControl终极指南:5步实现Windows风扇智能控制,让电脑散热更安静更高效

FanControl终极指南:5步实现Windows风扇智能控制,让电脑散热更安静更高效 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://g…...

文房四宝-徽墨

文房四宝,除了你已经熟悉的墨(以徽墨为代表),还包括笔、纸、砚。这套书写工具共同构成了中国传统文化中文房雅器的核心,每一宝都有其最具代表性的产地与传奇故事。简单来说就是:湖笔、徽墨、宣纸、端砚。&a…...