#include <iostream>
#include <fstream>
#include <queue>
#include <unordered_map>
#include <string>
using namespace std;
template <typename E>
struct TreeNode {
E data;
TreeNode* left;
TreeNode* right;
TreeNode(E d) : data(d), left(nullptr), right(nullptr) {}
};
template <typename E>
TreeNode<E>* generateHuffmanTree(E* arr, E invalid);
template <typename E>
struct Compare {
bool operator()(TreeNode<E>* a, TreeNode<E>* b) {
if (a->data == b->data) {
// 如果权重相同,比较字符的整数值以确保稳定性
return static_cast<int>(a->data) > static_cast<int>(b->data);
}
return a->data > b->data;
}
};
template <typename Weight>
void generateCode(TreeNode<Weight>* root, string code, unordered_map<Weight, string>& huffmanCodes);
bool readLine(ifstream& file, string& line);
void writeTreeInfo(TreeNode<char>* root, ofstream& outFile);
bool compress(const char* filename);
bool uncompress(const char* filename);
int main() {
int choice;
do {
cout << "1. 压缩文件\n2. 解压文件\n3. 退出\n请输入操作: ";
cin >> choice;
switch (choice) {
case 1:
{
char inputFilename[100];
cout << "请输入目标文件路径: ";
cin >> inputFilename;
if (compress(inputFilename)) {
cout << "压缩完成!\n";
}
else {
cout << "压缩失败,请检查输入文件路径。\n";
}
}
break;
case 2:
{
char compressedFilename[100];
cout << "请输入已压缩文件路径: ";
cin >> compressedFilename;
if (uncompress(compressedFilename)) {
cout << "解压完成!\n";
}
else {
cout << "解压失败,请检查输入文件路径。\n";
}
}
break;
case 3:
cout << "退出程序。\n";
break;
default:
cout << "无效的选择,请重新输入。\n";
}
} while (choice != 3);
return 0;
}
template <typename E>
TreeNode<E>* generateHuffmanTree(E* arr, E invalid) {
priority_queue<TreeNode<E>*, vector<TreeNode<E>*>, Compare<E>> minHeap;
for (int i = 0; arr[i] != invalid; ++i) {
minHeap.push(new TreeNode<E>(arr[i]));
}
while (minHeap.size() > 1) {
TreeNode<E>* left = minHeap.top();
minHeap.pop();
TreeNode<E>* right = minHeap.top();
minHeap.pop();
TreeNode<E>* newNode = new TreeNode<E>(left->data + right->data);
newNode->left = left;
newNode->right = right;
minHeap.push(newNode);
}
return minHeap.top();
}
template <typename Weight>
void generateCode(TreeNode<Weight>* root, string code, unordered_map<Weight, string>& huffmanCodes) {
if (root->left == nullptr && root->right == nullptr) {
huffmanCodes[root->data] = code;
return;
}
if (root->left != nullptr) {
generateCode(root->left, code + "0", huffmanCodes);
}
if (root->right != nullptr) {
generateCode(root->right, code + "1", huffmanCodes);
}
}
bool readLine(ifstream& file, string& line) {
if (getline(file, line)) {
return true;
}
return false;
}
void writeTreeInfo(TreeNode<char>* root, ofstream& outFile) {
if (root == nullptr) {
return;
}
if (root->left == nullptr && root->right == nullptr) {
outFile << "0" << root->data;
}
else {
outFile << "1";
writeTreeInfo(root->left, outFile);
writeTreeInfo(root->right, outFile);
}
}
bool compress(const char* filename) {
ifstream inFile(filename);
if (!inFile.is_open()) {
cout << "无法打开文件 " << filename << " 进行压缩。\n";
return false;
}
// 读取文件内容,统计字符频率
unordered_map<char, int> frequency;
char ch;
while (inFile.get(ch)) {
frequency[ch]++;
}
inFile.clear(); // 重置文件流状态
inFile.seekg(0); // 定位文件指针到文件开头
// 生成哈夫曼树
// 将读取到的字符放入数组,以null字符结束
char arr[256] = { 0 }; // 假设字符的范围是0到255
int index = 0;
while (inFile.get(ch)) {
arr[index++] = ch;
}
inFile.clear(); // 重置文件流状态
inFile.seekg(0); // 定位文件指针到文件开头
char invalid = '\0';
TreeNode<char>* huffmanRoot = generateHuffmanTree(arr, invalid);
// 生成哈夫曼编码
unordered_map<char, string> huffmanCodes;
generateCode(huffmanRoot, "", huffmanCodes);
// 写入树信息文件
ofstream treeInfoFile("tree_info.txt");
if (!treeInfoFile.is_open()) {
cout << "无法创建树信息文件。\n";
return false;
}
writeTreeInfo(huffmanRoot, treeInfoFile);
treeInfoFile.close();
// 重新打开输入文件,以便从头开始读取
inFile.close();
inFile.open(filename);
// 写入压缩文件
ofstream compressedFile("compressed.huf", ios::binary);
if (!compressedFile.is_open()) {
cout << "无法创建压缩文件。\n";
return false;
}
while (inFile.get(ch)) {
compressedFile << huffmanCodes[ch];
}
compressedFile.close();
inFile.close();
return true;
}
bool uncompress(const char* filename) {
// 读取树信息文件
ifstream treeInfoFile("tree_info.txt");
if (!treeInfoFile.is_open()) {
cout << "找不到树信息文件。\n";
return false;
}
// 还原哈夫曼树
char ch;
TreeNode<char>* huffmanRoot = new TreeNode<char>('\0');
TreeNode<char>* currentNode = huffmanRoot;
while (treeInfoFile.get(ch)) {
if (ch == '0') {
treeInfoFile.get(ch);
currentNode->data = ch;
currentNode = huffmanRoot;
}
else if (ch == '1') {
if (currentNode->left == nullptr) {
currentNode->left = new TreeNode<char>('\0');
currentNode = currentNode->left;
}
else if (currentNode->right == nullptr) {
currentNode->right = new TreeNode<char>('\0');
currentNode = currentNode->right;
}
}
}
treeInfoFile.close();
// 读取压缩文件
ifstream compressedFile(filename, ios::binary);
if (!compressedFile.is_open()) {
cout << "无法打开压缩文件。\n";
return false;
}
// 解压缩
char bit;
currentNode = huffmanRoot;
ofstream outFile("uncompressed.txt");
while (compressedFile.get(bit)) {
if (bit == '0') {
currentNode = currentNode->left;
}
else if (bit == '1') {
currentNode = currentNode->right;
}
if (currentNode->left == nullptr && currentNode->right == nullptr) {
outFile << currentNode->data;
currentNode = huffmanRoot;
}
}
compressedFile.close();
outFile.close();
return true;
}
自存草稿1
最新推荐文章于 2024-05-22 00:03:53 发布