0

0

c++中如何实现哈夫曼树_c++构建哈夫曼编码教程

冰火之心

冰火之心

发布时间:2026-01-05 09:56:02

|

870人浏览过

|

来源于php中文网

原创

哈夫曼编码实现的关键在于正确处理比特流的读写:需补零对齐、记录填充位数、用位掩码逐比特操作,避免使用std::bitset;建树要用std::priority_queue配std::greater,仅叶子节点生成编码,结果存map供O(1)查找。

c++中如何实现哈夫曼树_c++构建哈夫曼编码教程

哈夫曼树的核心是优先队列,不是手写排序

std::priority_queue 实现最小堆,比手动维护数组或链表高效得多。C++ 默认是最大堆,必须显式传入 std::greater 或自定义比较器,否则节点会按权重从大到小弹出,建树直接失败。

常见错误:只重载 operator 但没注意优先级方向——哈夫曼要求每次取两个**最小**权重的节点合并,所以比较逻辑必须让小权重“优先”被 pop。

  • 节点结构体里不要只存 weight,必须带 leftright 指针(或 shared_ptr),否则无法回溯生成编码
  • 优先队列类型要统一:所有元素都得是 shared_ptr,避免裸指针生命周期失控
  • 字符频次统计建议用 std::map,能覆盖全部 256 个字节值,不漏空格、换行等控制字符

构建过程必须合并节点,不能复用原始叶子节点

每轮从队列取两个节点,新建一个父节点,其 weight 为二者之和,左右子指针分别指向取出的节点。这个新节点再 push 回队列。重复直到队列只剩一个节点——它就是哈夫曼树根。

关键点:每次合并后,原来的两个节点不再是独立叶子,而是新节点的子树。如果误将原始字符节点反复加入队列(比如忘了 pop 掉已合并的),会导致无限循环或树结构错乱。

立即学习C++免费学习笔记(深入)”;

struct Node {
    unsigned char ch;
    int weight;
    std::shared_ptr left, right;
    Node(unsigned char c, int w) : ch(c), weight(w) {}
    Node(int w, std::shared_ptr l, std::shared_ptr r) 
        : weight(w), left(l), right(r) {}
};

auto cmp = [](const std::shared_ptr& a, const std::shared_ptr& b) { return a->weight > b->weight; // 小权重要先出,所以用 > }; std::priority_queue, std::vector>, decltype(cmp)> pq(cmp);

生成编码要用 DFS 递归,别用 BFS

哈夫曼编码本质是根到叶子的路径,左分支记 0、右分支记 1。DFS 天然适合边遍历边拼接编码字符串;BFS 虽然也能做,但需额外保存路径状态,容易出错且无优势。

Dreamphilic
Dreamphilic

一个基于web的工具,为用户提供AI生成的内容。

下载

注意终止条件:只在 node->left == nullptr && node->right == nullptr 时才记录编码(即叶子节点)。中间节点没有对应字符,不能输出。

  • 递归参数建议传 const std::shared_ptr& + 当前编码字符串 std::string code,避免拷贝开销
  • 编码结果存进 std::map,后续压缩时可 O(1) 查找
  • 如果输入数据含未出现的字符(如全英文文本里有中文),该字符不会出现在 map 中,查表前务必检查 find() 是否有效

压缩/解压时边界问题最常引发崩溃

哈夫曼编码长度不固定,最终比特流往往不是字节对齐的。写文件时必须补零并记录填充位数;读文件时先读头部的填充数,再逐比特解析——否则最后一个字节可能被截断或误读。

典型现象:压缩后文件比原文件还大,或解压出乱码。根本原因常是比特读写逻辑没处理好末尾字节的掩码与偏移。

  • 写入时用 std::vector 缓存字节,用 bit_count 记录当前字节已写几位,超 8 位就进位
  • 读取时同样维护 bit_pos(0–7)和当前字节,用 (byte >> (7 - bit_pos)) & 1 提取单比特
  • 不要试图用 std::bitset 做流式处理——它不支持动态追加和非整字节读取,反而增加复杂度

真正难的不是建树,是把变长比特串可靠地落盘和还原。这部分逻辑一旦写错,调试成本远高于树构建本身。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

314

2023.08.02

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

520

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

253

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1437

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

610

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

547

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

541

2024.04.29

mc.js网页版入口地址大全
mc.js网页版入口地址大全

本专题整合了mc.js网页版入口地址大全以及mc.js1.8.8版本汇总,阅读专题下面的文章了解更多详细内容。

34

2026.01.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 6.6万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 18.5万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 12.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号