使用c++语言,利用哈夫曼编码实现文件压缩解压
时间: 2023-12-14 11:38:59 浏览: 81
哈夫曼编码是一种基于最小化编码长度的编码方式,可以用于压缩文件。下面是使用C++语言实现哈夫曼编码的代码示例:
```c++
#include <iostream>
#include <queue>
#include <unordered_map>
#include <fstream>
#include <bitset>
using namespace std;
struct Node {
char ch;
int freq;
Node *left, *right;
Node(char ch, int freq, Node *left = NULL, Node *right = NULL) :
ch(ch), freq(freq), left(left), right(right) {};
};
struct Compare {
bool operator()(Node *a, Node *b) {
return a->freq > b->freq;
}
};
void encode(Node *root, string &code, unordered_map<char, string> &huffman_code) {
if (!root) return;
if (!root->left && !root->right) {
huffman_code[root->ch] = code;
return;
}
code.push_back('0');
encode(root->left, code, huffman_code);
code.pop_back();
code.push_back('1');
encode(root->right, code, huffman_code);
code.pop_back();
}
Node *build_huffman_tree(const unordered_map<char, int> &freq) {
priority_queue<Node *, vector<Node *>, Compare> min_heap;
for (auto p : freq) {
min_heap.push(new Node(p.first, p.second));
}
while (min_heap.size() > 1) {
auto left = min_heap.top();
min_heap.pop();
auto right = min_heap.top();
min_heap.pop();
auto parent = new Node('\0', left->freq + right->freq, left, right);
min_heap.push(parent);
}
return min_heap.top();
}
void generate_freq(const string &filename, unordered_map<char, int> &freq) {
ifstream infile(filename, ios::binary);
char ch;
while (infile.get(ch)) {
freq[ch]++;
}
infile.close();
}
void write_huffman_tree(ofstream &outfile, Node *root) {
if (!root) return;
if (!root->left && !root->right) {
outfile.put('1');
outfile.put(root->ch);
return;
}
outfile.put('0');
write_huffman_tree(outfile, root->left);
write_huffman_tree(outfile, root->right);
}
void compress(const string &filename, const string &compressed_filename) {
unordered_map<char, int> freq;
generate_freq(filename, freq);
auto root = build_huffman_tree(freq);
unordered_map<char, string> huffman_code;
string code;
encode(root, code, huffman_code);
ofstream outfile(compressed_filename, ios::binary);
write_huffman_tree(outfile, root);
outfile.put('\n');
ifstream infile(filename, ios::binary);
char ch;
string compressed_bits;
while (infile.get(ch)) {
compressed_bits += huffman_code[ch];
}
infile.close();
int offset = 0;
while (offset < compressed_bits.size()) {
bitset<8> bits;
for (int i = 0; i < 8 && offset < compressed_bits.size(); i++) {
bits[i] = compressed_bits[offset++] - '0';
}
outfile.put(bits.to_ulong());
}
outfile.close();
}
Node *read_huffman_tree(ifstream &infile) {
char ch;
infile.get(ch);
if (ch == '1') {
infile.get(ch);
return new Node(ch, 0);
}
auto left = read_huffman_tree(infile);
auto right = read_huffman_tree(infile);
return new Node('\0', 0, left, right);
}
void decode(const string &compressed_filename, const string &decompressed_filename) {
ifstream infile(compressed_filename, ios::binary);
auto root = read_huffman_tree(infile);
string compressed_bits;
char ch;
while (infile.get(ch)) {
bitset<8> bits(ch);
compressed_bits += bits.to_string();
}
infile.close();
ofstream outfile(decompressed_filename, ios::binary);
Node *node = root;
for (int i = 0; i < compressed_bits.size(); i++) {
if (compressed_bits[i] == '0') {
node = node->left;
} else {
node = node->right;
}
if (!node->left && !node->right) {
outfile.put(node->ch);
node = root;
}
}
outfile.close();
}
int main() {
string filename = "test.txt";
string compressed_filename = "test_compressed.bin";
string decompressed_filename = "test_decompressed.txt";
compress(filename, compressed_filename);
decode(compressed_filename, decompressed_filename);
return 0;
}
```
上述代码实现了文件的压缩和解压,通过读取文件生成字符频率表,再利用哈夫曼编码生成哈夫曼树。在压缩时,将哈夫曼树写入压缩文件中,并将文件内容进行编码,再将编码后的内容写入文件。在解压时,首先读取压缩文件中的哈夫曼树,再根据哈夫曼树对编码后的内容进行解码,并将解码后的内容写入解压文件。
阅读全文