Huffman-Compressor
Huffman-Compressor
基于霍夫曼编码实现的无损文件压缩与解压缩工具,使用C++编写,核心逻辑遵循霍夫曼编码的经典实现思路,支持任意类型文件的压缩和解压操作。
项目简介
霍夫曼编码是一种基于字符频率的可变长度前缀编码算法,本项目通过C++模板实现通用的霍夫曼树结构,完成文件的压缩(将字符替换为最短编码)与解压缩(通过编码还原原始字符),全程保证数据无损。
核心特性
- ✅ 无损压缩/解压缩:支持文本、二进制、图片等任意格式文件
- ✅ 通用模板设计:霍夫曼节点/树采用模板实现,适配不同字符/权重类型
- ✅ 内存安全:递归释放霍夫曼树节点,避免内存泄漏
- ✅ 命令行交互:简单的控制台交互流程,无需复杂参数
- ✅ 完整元数据存储:压缩文件包含原始文件大小、字符频率表,确保解压准确性
编译与运行
环境要求
- 支持C++11及以上标准的编译器(GCC、Clang、MSVC等)
- 任意操作系统(Windows/Linux/macOS)
编译命令
# GCC/Clang
g++ HuffCode.cpp -o huffman -std=c++11
# Windows MSVC (Developer Command Prompt)
cl HuffCode.cpp /EHsc /Fe:huffman.exe
运行程序
# 编译后直接执行
./huffman # Linux/macOS
huffman.exe # Windows
使用说明
程序运行后会进入交互界面,按提示操作即可:
1. 压缩文件
请选择操作: 1. 压缩 2. 解压缩
1
请输入源文件名:test.txt
请输入目标文件:test.huff
这在处理中,请等待………
处理结束
- 源文件:待压缩的原始文件路径(相对/绝对路径均可)
- 目标文件:压缩后的文件路径(建议使用
.huff后缀区分)
2. 解压缩文件
请选择操作: 1. 压缩 2. 解压缩
2
请输入压缩文件名:test.huff
请输入目标文件:test_restore.txt
这在解压中,请等待………
处理结束
- 压缩文件:之前生成的
.huff格式文件 - 目标文件:解压后的原始文件路径
核心实现说明
1. 霍夫曼节点设计
HuffNode:抽象基类,定义节点核心接口(获取权重、判断叶子节点、左右子节点操作)LeafNode:叶子节点,存储字符和对应权重InNode:内部节点,存储权重和左右子节点指针,析构时递归释放子节点
2. 霍夫曼树构建
- 小顶堆(优先队列)实现:按权重升序排列节点,每次取最小的两个节点合并
- 编码生成:递归遍历霍夫曼树,为每个叶子节点生成唯一的0/1编码
- 字符索引映射:将字符转换为0-255的索引,确保编码存储的唯一性
3. 压缩文件结构
压缩后的文件包含三部分: | 部分 | 说明 | 数据类型 | |---------------|--------------------------|-------------------| | 原始文件大小 | 记录原始文件的字节数 | unsigned long | | 字符频率表 | 256个字符的出现次数 | unsigned long[256]| | 编码数据 | 霍夫曼编码后的二进制数据 | 字节流(补0对齐) |
4. 压缩/解压流程
- 压缩:统计字符频率 → 构建霍夫曼树 → 生成字符编码 → 写入元数据 + 编码后数据
- 解压:读取元数据 → 重建霍夫曼树 → 解析编码数据 → 还原原始字符
注意事项
- 空文件处理:程序会检测空文件并直接退出,避免无效操作
- 路径问题:输入文件路径时确保正确,相对路径以程序运行目录为基准
- 小文件开销:小文件的压缩效果可能不明显(元数据占比过高),适合大文件压缩
- 编码唯一性:基于字符频率生成的霍夫曼编码保证前缀唯一,无解码歧义
常见问题
Q:压缩后的文件比原文件大?
A:霍夫曼编码的压缩效果依赖字符重复度,小文件/字符分布均匀的文件(如加密文件)可能出现元数据开销 > 压缩收益的情况,属于正常现象。
Q:解压后文件与原文件不一致?
A:请确保压缩/解压使用同一版本程序,且压缩文件未被修改(元数据损坏会导致解压异常)。
Q:程序运行时崩溃?
A:检查文件路径是否正确、文件是否被占用,或尝试使用绝对路径输入文件名。
许可证
本项目为开源学习用途,无明确许可证限制,可自由修改、分发和使用。
学习参考
本项目适合学习霍夫曼编码的核心原理:
- 贪心算法在霍夫曼树构建中的应用
- 优先队列(小顶堆)的使用
- 模板类/抽象类的设计与实现
- 文件二进制读写与字节操作
- 递归算法在树结构中的应用