自存草稿1

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值