admin管理员组文章数量:1624790
压缩前:
将pic.png拖到.exe文件上,可得到.zLzip压缩文件:
编码过程:
压缩过程:
将.zLzip压缩文件拖回可解压缩得到原文件:
顺便一提,当原文件内字符分布均衡时,其信息熵很低,压缩效果不太好。
代码如下(C++11)
main.cpp文件:
#include <cassert>
#include <cstdio>
#include <stdexcept>
#include <string>
#include "huffman_encoder.h"
using namespace std;
int main(int argc, char** argv) {
assert(argc >= 1);
string filename = argv[1]; // 读取输入(也可在界面中拖动)
zfish::HuffmanEncoder hec{
filename};
hec.run();
getchar();
return 0;
}
huffman_encoder.h 头文件:
#pragma once
#include <string>
namespace zfish {
using CodeType = unsigned long long;
using Byte = unsigned char;
// 码数
constexpr int kCodeNum = 256;
// 压缩识别符长度
constexpr int kLenOfZipName = 16;
// 文件名长度
constexpr int kLenOfFileName = 256;
// 文件大小值长度
constexpr int kLenOfFileSize = 8;
// 码频值长度
constexpr int kLenOfCodeFrequency = 8;
// 头文件信息长度
constexpr int kLenOfZipHeader = kLenOfZipName + kLenOfFileName +
kLenOfFileSize + kLenOfCodeFrequency * kCodeNum;
// 压缩 识别符
static const char kZipName[kLenOfZipName] = "zzzfish";
// 码点
struct HuffmanCodePoint {
Byte old_code; // 旧码
CodeType frequency; // 频率
CodeType new_code; // 新码
int length; // 新码长度
std::string new_code_str; // 新码字符串表示(debug用)
HuffmanCodePoint() : old_code(0), frequency(0), new_code(0), length(0) {
}
};
// Huffman 节点
struct HuffmanTreeNode {
CodeType weight; // 权重
HuffmanCodePoint* point; // 指向码点(叶子节点才有指向)
HuffmanTreeNode* left; // 左分支
HuffmanTreeNode* right; // 右分支
HuffmanTreeNode(CodeType weight = 0, HuffmanCodePoint* point = nullptr,
HuffmanTreeNode* left = nullptr,
HuffmanTreeNode* right = nullptr)
: weight(weight), point(point), left(left), right(right) {
}
};
// 自定义比较器,用于优先队列
struct CmparatorOfHuffmanTreeNode {
bool operator()(HuffmanTreeNode*& lhs, HuffmanTreeNode*& rhs) const {
return lhs->weight > rhs->weight;
}
};
class HuffmanEncoder {
public:
HuffmanEncoder(const std::string& inputFileName, bool isCompress = false);
~HuffmanEncoder();
// 禁止拷贝构造
HuffmanEncoder(const HuffmanEncoder&) = delete;
HuffmanEncoder& operator=(const HuffmanEncoder&) = delete;
/// 如果是未压缩的,则进行压缩,如果是压缩,则解压缩
void run();
// 统计频率
void statisticalFrequency();
// 构建 Huffman 树
HuffmanTreeNode* buildHuffmanTree();
// 获得 Huffman 编码
void initCodePoint(HuffmanTreeNode* node, CodeType new_code,
std::string new_code_str, int length);
// 压缩文件
void compress();
// 搜索节点,辅助于解码
bool findNode(HuffmanTreeNode*& node, Byte inputByte, int& pos);
// 解压缩
void uncompress();
// 打印哈夫曼编码信息
void printHuffmanEncodeInfo();
// 打印压缩或解压缩信息
void printInfo(const char* type);
// 获取输出文件名
std::string getOutputFileName() const {
return output_filename_;
}
// 判断两个文件是否相等
bool equalFile(const std::string& fileName1, const std::string& fileName2);
private:
// 释放节点
void freeNode(HuffmanTreeNode* node);
private:
HuffmanCodePoint points_[kCodeNum]; // 码
HuffmanTreeNode* root_; // Huffman树根节点
版权声明:本文标题:基于Huffman编码的压缩和解压缩小软件(附C++源码) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1726595920a1076837.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论