使用c++写出实验中要求的代码
时间: 2024-12-18 18:31:05 浏览: 12
根据您提供的实验要求,以下是C++代码的一个基本实现。这个实现包括了构建哈夫曼树、生成编码、压缩文件、存储哈夫曼树信息、读取哈夫曼树信息和解压文件的主要功能。
### HuffmanCoding.cpp
```cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <string>
using namespace std;
// 定义哈夫曼树节点
struct TreeNode {
char data;
int freq;
TreeNode *left, *right;
TreeNode(char d, int f) : data(d), freq(f), left(nullptr), right(nullptr) {}
};
// 定义比较器,用于优先队列
struct Compare {
bool operator()(TreeNode* l, TreeNode* r) {
return l->freq > r->freq;
}
};
// 生成哈夫曼树
TreeNode* buildHuffmanTree(unordered_map<char, int>& frequency) {
priority_queue<TreeNode*, vector<TreeNode*>, Compare> pq;
for (auto& pair : frequency) {
pq.push(new TreeNode(pair.first, pair.second));
}
while (pq.size() != 1) {
TreeNode* left = pq.top(); pq.pop();
TreeNode* right = pq.top(); pq.pop();
TreeNode* newNode = new TreeNode('$', left->freq + right->freq);
newNode->left = left;
newNode->right = right;
pq.push(newNode);
}
return pq.top();
}
// 生成哈夫曼编码
void generateCodes(TreeNode* root, string str, unordered_map<char, string>& huffmanCode) {
if (!root)
return;
if (!root->left && !root->right)
huffmanCode[root->data] = str;
generateCodes(root->left, str + "0", huffmanCode);
generateCodes(root->right, str + "1", huffmanCode);
}
// 压缩文件
bool compress(const char* inputFilePath, const char* outputFilePath, const char* treeInfoPath1, const char* treeInfoPath2) {
ifstream inputFile(inputFilePath, ios::binary);
ofstream outputFile(outputFilePath, ios::binary);
ofstream treeInfoFile1(treeInfoPath1, ios::binary);
ofstream treeInfoFile2(treeInfoPath2, ios::binary);
if (!inputFile || !outputFile || !treeInfoFile1 || !treeInfoFile2) {
cerr << "Error opening files." << endl;
return false;
}
unordered_map<char, int> frequency;
char ch;
while (inputFile.get(ch)) {
frequency[ch]++;
}
TreeNode* root = buildHuffmanTree(frequency);
unordered_map<char, string> huffmanCode;
generateCodes(root, "", huffmanCode);
// 存储哈夫曼树信息
preOrderTraversal(root, treeInfoFile1);
storeLeafNodes(root, treeInfoFile2);
// 压缩文件
inputFile.clear();
inputFile.seekg(0, ios::beg);
string encodedText;
while (inputFile.get(ch)) {
encodedText += huffmanCode[ch];
}
// 写入压缩文件
for (char c : encodedText) {
outputFile.put(c);
}
return true;
}
// 解压文件
bool uncompress(const char* inputFilePath, const char* outputFilePath, const char* treeInfoPath1, const char* treeInfoPath2) {
ifstream inputFile(inputFilePath, ios::binary);
ofstream outputFile(outputFilePath, ios::binary);
ifstream treeInfoFile1(treeInfoPath1, ios::binary);
ifstream treeInfoFile2(treeInfoPath2, ios::binary);
if (!inputFile || !outputFile || !treeInfoFile1 || !treeInfoFile2) {
cerr << "Error opening files." << endl;
return false;
}
TreeNode* root = readHuffmanTree(treeInfoFile1, treeInfoFile2);
string compressedData;
char ch;
while (inputFile.get(ch)) {
compressedData += ch;
}
TreeNode* node = root;
for (char bit : compressedData) {
if (bit == '0') {
node = node->left;
} else {
node = node->right;
}
if (!node->left && !node->right) {
outputFile.put(node->data);
node = root;
}
}
return true;
}
// 先序遍历哈夫曼树,存储树结构
void preOrderTraversal(TreeNode* root, ofstream& file) {
if (!root) {
file.put('0');
return;
}
file.put('1');
preOrderTraversal(root->left, file);
preOrderTraversal(root->right, file);
}
// 存储叶节点信息
void storeLeafNodes(TreeNode* root, ofstream& file) {
if (!root)
return;
if (!root->left && !root->right) {
file.put(root->data);
}
storeLeafNodes(root->left, file);
storeLeafNodes(root->right, file);
}
// 从文件中读取哈夫曼树
TreeNode* readHuffmanTree(ifstream& file1, ifstream& file2) {
char bit = file1.get();
if (bit == '0')
return nullptr;
TreeNode* node = new TreeNode('$', 0);
node->left = readHuffmanTree(file1, file2);
node->right = readHuffmanTree(file1, file2);
if (!node->left && !node->right) {
node->data = file2.get();
}
return node;
}
int main() {
const char* inputFilePath = "test.txt";
const char* outputFilePath = "compressed.bin";
const char* treeInfoPath1 = "tree_info1.txt";
const char* treeInfoPath2 = "tree_info2.txt";
compress(inputFilePath, outputFilePath, treeInfoPath1, treeInfoPath2);
uncompress(outputFilePath, "uncompressed.txt", treeInfoPath1, treeInfoPath2);
cout << "Compression and decompression completed successfully." << endl;
return 0;
}
```
### 说明
1. **构建哈夫曼树**:`buildHuffmanTree` 函数使用优先队列构建哈夫曼树。
2. **生成哈夫曼编码**:`generateCodes` 函数递归地生成每个字符的哈夫曼编码。
3. **压缩文件**:`compress` 函数读取输入文件,计算字符频率,构建哈夫曼树,生成编码,然后将编码后的数据写入输出文件。同时,存储哈夫曼树的结构和叶节点信息。
4. **解压文件**:`uncompress` 函数读取压缩文件和哈夫曼树信息,重建哈夫曼树,然后根据编码逐位解压数据并写入输出文件。
5. **辅助函数**:`preOrderTraversal` 和 `storeLeafNodes` 用于存储哈夫曼树的结构和叶节点信息。`readHuffmanTree` 用于从文件中读取哈夫曼树。
### 使用方法
1. 将上述代码保存为 `HuffmanCoding.cpp`。
2. 编译并运行程序:
```sh
g++ -o HuffmanCoding HuffmanCoding.cpp
./HuffmanCoding
```
3. 输入文件 `test.txt` 需要存在当前目录下。
希望这段代码能满足您的需求。如果有任何问题或需要进一步的帮助,请随时告诉我。
阅读全文