帮我用c++写一个利用Huffman编码实现文件压缩的代码
时间: 2024-03-16 11:42:55 浏览: 76
好的,下面是代码实现:
```c++
#include <iostream>
#include <fstream>
#include <queue>
#include <map>
using namespace std;
// 定义 Huffman 树节点
struct HuffmanTreeNode {
int weight; // 权值
char ch; // 字符
HuffmanTreeNode *left, *right; // 左右子节点
HuffmanTreeNode(int weight, char ch, HuffmanTreeNode *left, HuffmanTreeNode *right) {
this->weight = weight;
this->ch = ch;
this->left = left;
this->right = right;
}
};
// Huffman 编码
class HuffmanEncoding {
public:
HuffmanEncoding() {}
// 压缩文件
void compress(const string& input_file, const string& output_file) {
// 统计字符出现频率
map<char, int> freq_map = get_freq_map(input_file);
// 构建 Huffman 树
HuffmanTreeNode *root = build_huffman_tree(freq_map);
// 生成字符编码表
map<char, string> encoding_map = generate_encoding_map(root);
// 压缩文件
compress_file(input_file, output_file, encoding_map);
// 释放 Huffman 树节点
release_huffman_tree(root);
}
// 解压缩文件
void decompress(const string& input_file, const string& output_file) {
// 解析 Huffman 树
HuffmanTreeNode *root = parse_huffman_tree(input_file);
// 解压缩文件
decompress_file(input_file, output_file, root);
// 释放 Huffman 树节点
release_huffman_tree(root);
}
private:
// 统计字符出现频率
map<char, int> get_freq_map(const string& input_file) {
map<char, int> freq_map;
ifstream fin(input_file, ios::in | ios::binary);
char ch;
while (fin.get(ch)) {
freq_map[ch]++;
}
fin.close();
return freq_map;
}
// 构建 Huffman 树
HuffmanTreeNode *build_huffman_tree(const map<char, int>& freq_map) {
auto cmp = [](HuffmanTreeNode *a, HuffmanTreeNode *b) {
return a->weight > b->weight;
};
priority_queue<HuffmanTreeNode*, vector<HuffmanTreeNode*>, decltype(cmp)> pq(cmp);
for (auto& freq_pair : freq_map) {
pq.push(new HuffmanTreeNode(freq_pair.second, freq_pair.first, nullptr, nullptr));
}
while (pq.size() > 1) {
HuffmanTreeNode *left = pq.top();
pq.pop();
HuffmanTreeNode *right = pq.top();
pq.pop();
pq.push(new HuffmanTreeNode(left->weight + right->weight, '\0', left, right));
}
HuffmanTreeNode *root = pq.top();
pq.pop();
return root;
}
// 生成字符编码表
map<char, string> generate_encoding_map(HuffmanTreeNode *root) {
map<char, string> encoding_map;
string code;
generate_encoding_map_helper(root, code, encoding_map);
return encoding_map;
}
void generate_encoding_map_helper(HuffmanTreeNode *node, string& code, map<char, string>& encoding_map) {
if (node == nullptr) {
return;
}
if (node->left == nullptr && node->right == nullptr) {
encoding_map[node->ch] = code;
return;
}
code.push_back('0');
generate_encoding_map_helper(node->left, code, encoding_map);
code.pop_back();
code.push_back('1');
generate_encoding_map_helper(node->right, code, encoding_map);
code.pop_back();
}
// 压缩文件
void compress_file(const string& input_file, const string& output_file, const map<char, string>& encoding_map) {
ifstream fin(input_file, ios::in | ios::binary);
ofstream fout(output_file, ios::out | ios::binary);
char ch;
string code;
while (fin.get(ch)) {
code += encoding_map.at(ch);
while (code.length() >= 8) {
char byte = 0;
for (int i = 0; i < 8; i++) {
if (code[i] == '1') {
byte |= (1 << (7 - i));
}
}
fout.put(byte);
code.erase(0, 8);
}
}
if (!code.empty()) {
char byte = 0;
for (int i = 0; i < code.length(); i++) {
if (code[i] == '1') {
byte |= (1 << (7 - i));
}
}
fout.put(byte);
}
fin.close();
fout.close();
}
// 解析 Huffman 树
HuffmanTreeNode *parse_huffman_tree(const string& input_file) {
ifstream fin(input_file, ios::in | ios::binary);
char ch;
fin.get(ch);
if (ch == '\0') {
fin.close();
return nullptr;
}
HuffmanTreeNode *root = new HuffmanTreeNode(0, '\0', nullptr, nullptr);
parse_huffman_tree_helper(root, fin);
fin.close();
return root;
}
void parse_huffman_tree_helper(HuffmanTreeNode *node, ifstream& fin) {
char ch;
fin.get(ch);
if (ch == '1') {
node->left = new HuffmanTreeNode(0, '\0', nullptr, nullptr);
parse_huffman_tree_helper(node->left, fin);
}
fin.get(ch);
if (ch == '1') {
node->right = new HuffmanTreeNode(0, '\0', nullptr, nullptr);
parse_huffman_tree_helper(node->right, fin);
}
}
// 解压缩文件
void decompress_file(const string& input_file, const string& output_file, HuffmanTreeNode *root) {
ifstream fin(input_file, ios::in | ios::binary);
ofstream fout(output_file, ios::out | ios::binary);
if (root == nullptr) {
fin.close();
fout.close();
return;
}
HuffmanTreeNode *node = root;
char ch;
while (fin.get(ch)) {
for (int i = 7; i >= 0; i--) {
if ((ch >> i) & 1) {
node = node->right;
} else {
node = node->left;
}
if (node->left == nullptr && node->right == nullptr) {
fout.put(node->ch);
node = root;
}
}
}
fin.close();
fout.close();
}
// 释放 Huffman 树节点
void release_huffman_tree(HuffmanTreeNode *node) {
if (node == nullptr) {
return;
}
release_huffman_tree(node->left);
release_huffman_tree(node->right);
delete node;
}
};
int main() {
HuffmanEncoding huffman;
string input_file = "input.txt";
string output_file = "output.bin";
// 压缩文件
huffman.compress(input_file, output_file);
// 解压缩文件
huffman.decompress(output_file, "output.txt");
return 0;
}
```
在这个例子中,我们使用了 C++ 的 STL 库中的 `map`、`priority_queue` 和文件流相关的类来实现 Huffman 编码。该程序可以读取指定的文件,生成 Huffman 编码并将其写入到输出文件中。另外,还可以读取 Huffman 编码并将其解压回原始文件。
阅读全文