读取一个Txt文本参与哈夫曼编码压缩文本运算

读取文本时会读取空格和换行符参与哈夫曼编码运算,等到解码时可还原原本的文段

#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>
#include <fstream>
#include <string>
#include <windows.h>
#include <commdlg.h>

using namespace std;

// 结点类
class Node {
public:
    char ch;        // 字符
    int freq;       // 字符出现频率
    Node* left;     // 左孩子
    Node* right;    // 右孩子

    Node() {}

    Node(char c, int f) {
        ch = c;
        freq = f;
        left = nullptr;
        right = nullptr;
    }

    ~Node() {
        delete left;
        delete right;
    }
};

// 比较函数,用于优先队列中的排序
struct cmp {
    bool operator() (const Node* a, const Node* b) {
        return a->freq > b->freq;
    }
};

// 建立哈夫曼树
Node* buildHuffmanTree(unordered_map<char, int>& freqMap) {
    priority_queue<Node*, vector<Node*>, cmp> pq;

    for (auto it : freqMap) {
        pq.push(new Node(it.first, it.second));
    }

    while (pq.size() > 1) {
        Node* left = pq.top(); pq.pop();
        Node* right = pq.top(); pq.pop();

        Node* parent = new Node('$', left->freq + right->freq);
        parent->left = left;
        parent->right = right;

        pq.push(parent);
    }

    return pq.top();
}

// 哈夫曼编码哈希表
void buildHuffmanCode(Node* root, string code, unordered_map<char, string>& huffmanCode) {
    if (!root) return;

    if (!root->left && !root->right) {   // 叶子结点
        huffmanCode[root->ch] = code;
    }

    buildHuffmanCode(root->left, code + "0", huffmanCode);
    buildHuffmanCode(root->right, code + "1", huffmanCode);
}

// 哈夫曼编码压缩
string compress(string text, unordered_map<char, string>& huffmanCode) {
    string compressedText = "";

    for (char c : text) {
        compressedText += huffmanCode[c];
    }

    return compressedText;
}

// 哈夫曼解码,返回原始文本
string decompress(string compressedText, Node* root) {
    string text = "";
    Node* cur = root;

    for (char c : compressedText) {
        if (c == '0') {
            cur = cur->left;
        }
        else {
            cur = cur->right;
        }

        if (!cur->left && !cur->right) {   // 叶子结点
            text += cur->ch;
            cur = root;     // 重置为根节点
        }
    }

    return text;
}


string text;
string line;


void Hafuman() {
    
    /*cout << "请输出一段字符" << endl;*/
    //getline(cin, text);    // 改为使用getline读入一行字符串
    cout << endl;

    // 统计字符出现频率
    unordered_map<char, int> freqMap;
    for (char c : text) {
        freqMap[c]++;
    }
    freqMap[' '] = 1;   // 统计空格

    // 建立哈夫曼树
    Node* root = buildHuffmanTree(freqMap);

    // 建立哈夫曼编码哈希表
    unordered_map<char, string> huffmanCode;
    buildHuffmanCode(root, "", huffmanCode);

    // 压缩文本
    string compressedText = compress(text, huffmanCode);

    // 输出压缩后的文本和哈夫曼编码表
    cout << "压缩后的文本: " << compressedText << endl;

    cout << "哈夫曼编码:" << endl;//数量从大到小排序;注意:文本参与哈夫曼压缩编码的包含:空格和换行符
    

    vector<pair<char, int>> sortedFreqMap(freqMap.begin(), freqMap.end());
    sort(sortedFreqMap.begin(), sortedFreqMap.end(), [](const auto& a, const auto& b) {
        return a.second > b.second;
        });

    // 按顺序输出哈夫曼编码
    for (auto& it : sortedFreqMap) {
        char c = it.first;
        if (huffmanCode.count(c)) {
            cout << c << " :Numbers: " << freqMap[c] << " Huffman Code: " << huffmanCode[c] << endl;
        }
    }

    // 解压文本
    string decompressedText = decompress(compressedText, root);

    // 输出解压后的原始文本
    cout << "解压后的原始文本: " << decompressedText << endl;

    delete root;
}

int readInfo() {
    // 打开文件选择对话框
    OPENFILENAMEA ofn;
    char szFile[260] = { 0 };
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;

    if (GetOpenFileNameA(&ofn) == TRUE) {
        // 将 char 类型字符串转换为 wchar_t 类型字符串
        int len = MultiByteToWideChar(CP_UTF8, 0, szFile, -1, NULL, 0);
        wchar_t* wstr = new wchar_t[len];
        MultiByteToWideChar(CP_UTF8, 0, szFile, -1, wstr, len);
        wstring filename(wstr);
        delete[] wstr;

        ifstream infile(filename);

        if (!infile.is_open()) {
            cout << "Failed to open file." << endl;
            return 1;
        }

        
        while (getline(infile, line)) {
            text += line + "\n";
        }

        cout << "The content of the file is:\n" << text;

        infile.close();

        return 0;
    }
    else {
        cout << "User canceled the file selection dialog." << endl;
        return 1;
    }
}

int main() {
    readInfo();
    Hafuman();
    
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H._

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值