C++用二叉树将文本文档中的字符进行霍夫曼编码
时间: 2024-02-16 11:01:04 浏览: 24
好的,我可以为您解答这个问题。
首先,霍夫曼编码是一种用于数据压缩的算法,它使用可变长度的编码来表示不同的符号。在霍夫曼编码中,频率较高的符号使用较短的编码,而频率较低的符号使用较长的编码,从而实现数据压缩的效果。
在C++中使用二叉树实现霍夫曼编码可以分为以下几个步骤:
1. 统计文本文档中各个字符出现的频率,并将它们存储在一个频率表中。
2. 根据频率表构建霍夫曼树。霍夫曼树的构建过程可以使用贪心算法,即每次选取频率最小的两个节点构造一个新的节点,直到所有节点都被构造为止。在构造过程中,每个节点的权值应为其子节点的权值之和。
3. 对霍夫曼树进行遍历,生成每个字符的编码。由于霍夫曼树是一棵二叉树,因此可以使用递归的方式进行遍历。遍历过程中,每次向左走时添加一个0,向右走时添加一个1,直到到达叶子节点时,得到该字符的编码。
4. 将文本文档中的每个字符替换为其对应的霍夫曼编码,并将编码后的文本存储到一个新的文件中。
这是一个比较简单的C++实现方法,如果您需要更详细的代码实现可以参考一些相关的教程和代码示例。
相关问题
C++用二帮我写一个C++程序用二叉树将文本文档中的字符进行霍夫曼编码
好的,下面是一个简单的C++程序,使用二叉树将文本文档中的字符进行霍夫曼编码:
```c++
#include <iostream>
#include <fstream>
#include <queue>
#include <unordered_map>
#include <bitset>
using namespace std;
//定义霍夫曼树的节点结构体
struct HuffmanNode {
char ch; //字符
int freq; //出现频率
HuffmanNode *left; //左子节点
HuffmanNode *right; //右子节点
HuffmanNode(char ch, int freq, HuffmanNode *left = nullptr, HuffmanNode *right = nullptr) {
this->ch = ch;
this->freq = freq;
this->left = left;
this->right = right;
}
};
//定义优先队列的比较函数
struct Compare {
bool operator()(HuffmanNode *a, HuffmanNode *b) {
return a->freq > b->freq;
}
};
//统计文本文档中各个字符出现的频率
unordered_map<char, int> getFreqTable(string filename) {
unordered_map<char, int> freq_table;
ifstream infile(filename);
char ch;
while (infile >> noskipws >> ch) {
freq_table[ch]++;
}
infile.close();
return freq_table;
}
//根据频率表构建霍夫曼树
HuffmanNode *buildHuffmanTree(unordered_map<char, int> freq_table) {
priority_queue<HuffmanNode *, vector<HuffmanNode *>, Compare> pq;
for (auto it = freq_table.begin(); it != freq_table.end(); it++) {
pq.push(new HuffmanNode(it->first, it->second));
}
while (pq.size() > 1) {
HuffmanNode *node1 = pq.top();
pq.pop();
HuffmanNode *node2 = pq.top();
pq.pop();
pq.push(new HuffmanNode('\0', node1->freq + node2->freq, node1, node2));
}
return pq.top();
}
//遍历霍夫曼树,生成每个字符的编码
void generateCodeTable(HuffmanNode *root, unordered_map<char, string> &code_table, string code = "") {
if (root == nullptr) {
return;
}
if (root->left == nullptr && root->right == nullptr) {
code_table[root->ch] = code;
}
generateCodeTable(root->left, code_table, code + "0");
generateCodeTable(root->right, code_table, code + "1");
}
//将文本文档中的每个字符替换为其对应的霍夫曼编码,并将编码后的文本存储到一个新的文件中
void compressFile(string input_filename, string output_filename, unordered_map<char, string> code_table) {
ifstream infile(input_filename);
ofstream outfile(output_filename);
char ch;
string code;
while (infile >> noskipws >> ch) {
code += code_table[ch];
while (code.size() >= 8) {
bitset<8> b(code.substr(0, 8));
code = code.substr(8);
outfile << (char)b.to_ulong();
}
}
if (code.size() > 0) {
bitset<8> b(code + string(8 - code.size(), '0'));
outfile << (char)b.to_ulong();
}
infile.close();
outfile.close();
}
//解码函数,将编码后的文本解码为原始文本
void decompressFile(string input_filename, string output_filename, HuffmanNode *root) {
ifstream infile(input_filename);
ofstream outfile(output_filename);
HuffmanNode *cur = root;
char ch;
while (infile >> noskipws >> ch) {
bitset<8> b(ch);
for (int i = 7; i >= 0; i--) {
if (b[i] == 0) {
cur = cur->left;
} else {
cur = cur->right;
}
if (cur->left == nullptr && cur->right == nullptr) {
outfile << cur->ch;
cur = root;
}
}
}
infile.close();
outfile.close();
}
int main() {
string input_filename = "input.txt";
string output_filename = "output.bin";
string decompressed_filename = "decompressed.txt";
unordered_map<char, int> freq_table = getFreqTable(input_filename);
HuffmanNode *root = buildHuffmanTree(freq_table);
unordered_map<char, string> code_table;
generateCodeTable(root, code_table);
compressFile(input_filename, output_filename, code_table);
decompressFile(output_filename, decompressed_filename, root);
return 0;
}
```
这个程序会读取名为"input.txt"的文本文档,并将其中的字符进行霍夫曼编码,将编码后的结果存储到名为"output.bin"的文件中。然后,程序会将"output.bin"文件中的编码解码为原始文本,并将结果存储到名为"decompressed.txt"的文件中。
帮我写一个C++用二叉树进行霍夫曼编码
好的,下面是一个简单的C++实现,包括字符频率的统计、霍夫曼树的构建、字符编码的生成和文件压缩解压等功能:
```c++
#include <iostream>
#include <fstream>
#include <queue>
#include <unordered_map>
#include <vector>
using namespace std;
struct Node {
char ch;
int freq;
Node *left, *right;
Node(char ch, int freq, Node *left = nullptr, Node *right = nullptr) {
this->ch = ch;
this->freq = freq;
this->left = left;
this->right = right;
}
~Node() {
delete left;
delete right;
}
};
struct Compare {
bool operator()(Node *a, Node *b) {
return a->freq > b->freq;
}
};
class Huffman {
public:
Huffman() {}
void compress(const string &in_file, const string &out_file) {
unordered_map<char, int> freq_map = count_freq(in_file);
Node *root = build_tree(freq_map);
unordered_map<char, string> code_map = generate_code(root);
ifstream fin(in_file, ios::binary);
ofstream fout(out_file, ios::binary);
int num_bits = 0;
char buffer = 0;
while (true) {
char ch = fin.get();
if (fin.eof()) break;
string code = code_map[ch];
for (char bit : code) {
buffer = (buffer << 1) | (bit - '0');
if (++num_bits == 8) {
fout.put(buffer);
buffer = 0;
num_bits = 0;
}
}
}
if (num_bits > 0) {
buffer <<= (8 - num_bits);
fout.put(buffer);
}
fin.close();
fout.close();
}
void decompress(const string &in_file, const string &out_file) {
ifstream fin(in_file, ios::binary);
ofstream fout(out_file, ios::binary);
Node *root = read_tree(fin);
Node *p = root;
int num_bits = 0;
char buffer = fin.get();
while (true) {
if (p->left == nullptr && p->right == nullptr) {
fout.put(p->ch);
p = root;
} else {
char bit = (buffer >> (7 - num_bits)) & 1;
p = (bit == 0) ? p->left : p->right;
if (++num_bits == 8) {
buffer = fin.get();
num_bits = 0;
}
}
if (fin.eof()) break;
}
delete root;
fin.close();
fout.close();
}
private:
unordered_map<char, int> count_freq(const string &in_file) {
unordered_map<char, int> freq_map;
ifstream fin(in_file, ios::binary);
while (true) {
char ch = fin.get();
if (fin.eof()) break;
freq_map[ch]++;
}
fin.close();
return freq_map;
}
Node *build_tree(const unordered_map<char, int> &freq_map) {
priority_queue<Node*, vector<Node*>, Compare> pq;
for (auto &p : freq_map) {
pq.push(new Node(p.first, p.second));
}
while (pq.size() > 1) {
Node *left = pq.top(); pq.pop();
Node *right = pq.top(); pq.pop();
Node *parent = new Node('\0', left->freq + right->freq, left, right);
pq.push(parent);
}
return pq.top();
}
unordered_map<char, string> generate_code(Node *root) {
unordered_map<char, string> code_map;
string code;
generate_code_helper(root, code, code_map);
return code_map;
}
void generate_code_helper(Node *p, string &code, unordered_map<char, string> &code_map) {
if (p == nullptr) return;
if (p->left == nullptr && p->right == nullptr) {
code_map[p->ch] = code;
return;
}
code.push_back('0');
generate_code_helper(p->left, code, code_map);
code.pop_back();
code.push_back('1');
generate_code_helper(p->right, code, code_map);
code.pop_back();
}
Node *read_tree(ifstream &fin) {
char ch = fin.get();
if (ch == 'L') {
return new Node(fin.get(), 0);
} else {
Node *left = read_tree(fin);
Node *right = read_tree(fin);
return new Node('\0', 0, left, right);
}
}
void write_tree(Node *p, ofstream &fout) {
if (p->left == nullptr && p->right == nullptr) {
fout.put('L');
fout.put(p->ch);
} else {
fout.put('I');
write_tree(p->left, fout);
write_tree(p->right, fout);
}
}
};
int main() {
Huffman huffman;
huffman.compress("input.txt", "output.bin");
huffman.decompress("output.bin", "output.txt");
return 0;
}
```
这里假设待压缩的文件为文本文件,输入输出文件名分别为`input.txt`和`output.txt`,压缩后的二进制文件为`output.bin`。在压缩时,首先统计每个字符出现的频率,然后利用优先队列构建霍夫曼树,生成每个字符的编码,将每个字符替换为其对应的编码,得到压缩后的文件。在解压时,读入压缩后的文件,根据编码逆向遍历霍夫曼树,得到原字符,依次输出即可。