c++利用哈夫曼编码实现文件的压缩加密和解压缩解密

  1. 需求分析

@1:编码实现哈夫曼树,然后根据数据建立哈夫曼树,然后显示所有的字符的哈夫曼编码

@2:实现哈夫曼编码和解码 并通过编码实现文本文件的压缩 通过解码实现压缩文件的解压缩

  1. 概要设计

@1:在二叉树的基础上实现哈夫曼树的数据结构

@2:读取文本文件-->对字符频度进行统计-->构建哈夫曼树-->进行哈夫曼编码-->通过哈夫曼编码将文本文件压缩输出到压缩文件中

  1. 详细设计

@1:哈夫曼树的实现以及哈夫曼编码:

哈夫曼树的是是实现思路:

给定一个字符集合,统计字符出现的频率,并按照频率从小到大排序。取出频率最小的两个字符,将它们作为叶子节点构建一棵二叉树(可以使用任意一种二叉树表示方式,比如孩子兄弟表示法)。以该二叉树为基础,再次取出频率最小的两个字符,将它们添加到这棵二叉树中(作为兄弟或者作为父节点的左右孩子),得到一棵较大的二叉树。重复上述步骤,直到所有字符都被添加到二叉树中。此时,生成的二叉树即为哈夫曼树。根据哈夫曼树的构建规则,左子树代表频率较小的字符,右子树代表频率较大的字符。对于每一个叶子节点,记录其路径所代表的二进制编码即为该字符的哈夫曼编码。

 

 

@2:哈夫曼编码器和解码器是实现文本文件的压缩和解压缩

编码器实现压缩文件:

压缩原理:字符频度越大的字符的哈夫曼编码越短 那么就可以用哈夫曼编码来替换原字符的编码 从而实现解压缩,大致如下图:

 

8b2dd168e0f5482fab863dc3d272e10c.png

 

压缩的流程:

首先一个字符一个字符的读取待压缩文件 统计字符的种数以及字符出现的频度

为了解压缩时重构哈夫曼树 所以此时要将字符的出现的字符种数,字符以及相应的频度写入待压缩文件 然后紧接着写入压缩文件的长度

然后根据字符以及字符频度创建哈夫曼树 进行哈夫曼编码

然后以二进制的方式一个一个字节地遍历待压缩文件 准备一个中间空字符tempchar和计数器num 匹配每个字节对应的哈夫曼编码

然后通过遍历哈弗编码进行位操作每遍历一位哈夫曼编码就将tempchar左移一位 num自增1 如果当前哈夫曼编码是1就将tempchar|1 ,当num=8的时候将tempchar写入压缩文件 ,然后将tempchar 和num复原继续遍历哈夫曼编码,直到遍历完待压缩文件,如果最后的哈夫曼编码不足8位那么就在后面补0 补齐8位

 

解压缩流程:

首先从压缩文件种读取字符以及字符频度重构哈弗曼树 然后读取文件长度并记录

然后一个字节一个字节地遍历压缩文件之后的字符  ,从根节点出发,并且对每个字节的每一位通过位运算遍历 如果是1 移动到有孩子 如果是0就移动到左孩子 只要判断移动到了叶子结点 就将叶子节点对应的字符写入到解压缩之后的文件中,

 

项目效果演示:

主界面:

614b1675bc9b464489cf8ea7cafca776.png

功能1展示:

0b315c02687143e19984c35388c04cb1.png

 85bb42842c664615a50ede229e4aa783.png

 

功能2展示:

ad2f01d7dc794b95b50f6c3a46f58877.png

功能3展示:

  • 9
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
哈夫曼编码是一种常用的文件压缩算法,它通过对文件中的字符进行编码,使得文件的存储空间得到了有效的压缩。下面是C++语言实现哈夫曼编码文件压缩解压程序。 首先,我们需要定义哈夫曼树的节点结构体: ```c++ struct HuffmanNode { unsigned char ch; // 存储字符 int freq; // 存储字符出现的频率 HuffmanNode *left; // 指向左子树的指针 HuffmanNode *right;// 指向右子树的指针 }; ``` 接着,我们需要定义一个比较函数来用于建立哈夫曼树时的节点排序: ```c++ struct compare { bool operator()(const HuffmanNode *a, const HuffmanNode *b) const { return a->freq > b->freq; } }; ``` 然后,我们需要定义一个函数来建立哈夫曼树: ```c++ HuffmanNode* buildHuffmanTree(map<unsigned char, int> freqMap) { priority_queue<HuffmanNode*, vector<HuffmanNode*>, compare> pq; // 初始化优先队列 for (auto it : freqMap) { HuffmanNode *node = new HuffmanNode(); node->ch = it.first; node->freq = it.second; node->left = nullptr; node->right = nullptr; pq.push(node); } // 建立哈夫曼树 while (pq.size() > 1) { HuffmanNode *left = pq.top(); pq.pop(); HuffmanNode *right = pq.top(); pq.pop(); HuffmanNode *parent = new HuffmanNode(); parent->ch = 0; parent->freq = left->freq + right->freq; parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } ``` 接下来,我们需要定义一个函数来生成每个字符的哈夫曼编码: ```c++ void generateHuffmanCode(HuffmanNode *root, string code, map<unsigned char, string> &huffmanCodeMap) { if (root == nullptr) return; if (root->left == nullptr && root->right == nullptr) { huffmanCodeMap[root->ch] = code; return; } generateHuffmanCode(root->left, code + "0", huffmanCodeMap); generateHuffmanCode(root->right, code + "1", huffmanCodeMap); } ``` 然后,我们需要定义一个函数来进行文件压缩: ```c++ void compressFile(string inputFile, string outputFile) { ifstream fin(inputFile, ios::binary); ofstream fout(outputFile, ios::binary); // 统计每个字符出现的频率 map<unsigned char, int> freqMap; char ch; while (fin.read(&ch, sizeof(char))) { freqMap[ch]++; } // 建立哈夫曼树 HuffmanNode *root = buildHuffmanTree(freqMap); // 生成哈夫曼编码 map<unsigned char, string> huffmanCodeMap; generateHuffmanCode(root, "", huffmanCodeMap); // 写入哈夫曼编码 int codeSize = huffmanCodeMap.size(); fout.write((char*)&codeSize, sizeof(int)); for (auto it : huffmanCodeMap) { fout.write((char*)&it.first, sizeof(unsigned char)); int len = it.second.size(); fout.write((char*)&len, sizeof(int)); fout.write(it.second.c_str(), len * sizeof(char)); } // 压缩文件内容 fin.clear(); fin.seekg(0, ios::beg); string code; while (fin.read(&ch, sizeof(char))) { code += huffmanCodeMap[ch]; while (code.size() >= 8) { unsigned char byte = 0; for (int i = 0; i < 8; i++) { if (code[i] == '1') { byte |= (1 << (7 - i)); } } fout.write((char*)&byte, sizeof(unsigned char)); code = code.substr(8); } } if (code.size() > 0) { unsigned char byte = 0; for (int i = 0; i < code.size(); i++) { if (code[i] == '1') { byte |= (1 << (7 - i)); } } fout.write((char*)&byte, sizeof(unsigned char)); } // 释放内存 delete root; fin.close(); fout.close(); } ``` 最后,我们需要定义一个函数来进行文件的解压: ```c++ void decompressFile(string inputFile, string outputFile) { ifstream fin(inputFile, ios::binary); ofstream fout(outputFile, ios::binary); // 读取哈夫曼编码 int codeSize; fin.read((char*)&codeSize, sizeof(int)); map<unsigned char, string> huffmanCodeMap; for (int i = 0; i < codeSize; i++) { unsigned char ch; int len; fin.read((char*)&ch, sizeof(unsigned char)); fin.read((char*)&len, sizeof(int)); char *code = new char[len + 1]; fin.read(code, len * sizeof(char)); code[len] = '\0'; huffmanCodeMap[ch] = code; delete[] code; } // 解压文件内容 string code; char ch; while (fin.read(&ch, sizeof(char))) { for (int i = 7; i >= 0; i--) { if (ch & (1 << i)) { code += '1'; } else { code += '0'; } for (auto it : huffmanCodeMap) { if (it.second == code) { fout.write((char*)&it.first, sizeof(unsigned char)); code.clear(); } } } } fin.close(); fout.close(); } ``` 使用以上函数即可进行文件压缩和解压。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pp不会算法^v^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值