Huffman文件解码

【问题描述】

给定一组字符的Huffman编码表(从标准输入读取),给定一个用该编码表进行编码的Huffman编码文件(存在当前目录下的in.txt中),编写程序对Huffman编码文件进行解码。

例如给定的一组字符的Huffman编码表为:

6

1:111

2:0

+:110

*:1010

=:1011

8:100

第一行的6表示要对6个不同的字符进行编码,后面每行中冒号(:)左边的字符为待编码的字符,右边为其Huffman编码,冒号两边无空格。对于该编码表,对应的Huffman树(树中左分支表示0,右分支表示1)应为:

假如Huffman编码文件in.txt中的内容(由0和1字符组成的序列)为:

111011010010110101010011001100

则遍历上述Huffman树即可对该文件进行解码,解码后的文件内容为:

12+8=2*8+2+2

【输入形式】

先从标准输入读入待编码的字符个数(大于等于2,小于等于30),然后分行输入各字符的Huffman编码(先输入字符,再输入其编码,字符和编码中间以一个英文字符冒号:分隔),编码只由0和1组成。

Huffman编码文件为当前目录下的in.txt文本文件,即:其中的0和1都是以单个字符的形式存储,文件末尾有一个回车换行符。

【输出形式】

将解码后的文件内容输出到标准输出上

【样例输入】

6

1:111

2:0

+:110

*:1010

=:1011

8:100

假如in.txt中的内容为:

111011010010110101010011001100

【样例输出】

12+8=2*8+2+2

【样例说明】

从标准输入读取了6个字符的Huffman编码,因为规定Huffman树中左分支表示0,右分支表示1,所以利用该编码表可构造上述Huffman树(见图1)。遍历该Huffman树对编码文件in.txt的进行解码,即可得到解码后的原文件内容。

【评分标准】

该题要求根据字符的Huffman编码表对编码文件进行解码。

解答

对每一个字符都是Huffman树上的一条路径,0往左子树走,1往右子树走,叶子结点为字符

所以在传入根的情况下对每条路径进行建树,若该节点不存在则新建,最后一个节点为叶子,存入值

查询同理

代码:
(希冀平台文件输入离谱导致码风奇怪)

#include<iostream>
#include<sstream>
#include<fstream>
#include<string>
using namespace std;

struct Node {
    char data;
    Node* left, *right;
};

void build(Node* &root, char c,string cod) {
    int len = cod.length();
    Node* p = root;
    for (int i = 0; i < len; i++) {
        if (cod[i] == '0') {
            if (p->left)p = p->left;
            else {
                p->left = new Node{};
                p = p->left;
            }
        }
        else{
            if (p->right)p = p->right;
            else {
                p->right = new Node{};
                p = p->right;
            }
        }
    }
    p->data = c;
}

int main() {
    Node* root = new Node{};

    int n;
    cin >> n; cin.ignore();
    for (int i = 0; i < n; i++) {
        string line;
        getline(cin, line);

        istringstream iss(line);
        string data;

        iss >> data;
        char ch = data[0];
        data = data.substr(2,data.length()-2 );
        build(root, ch, data);
    }

    string s;
    fstream in("in.txt");
    in >> s;
    int len = s.length();
    Node* p = root;
    for (int i = 0; i < len;i++) {
        if (s[i] == '0'&&p->left)  p = p->left;
        else if(s[i]=='1'&&p->right)p = p->right;
        else {
            cout << p->data;
            p = root;
            i--;//多走一步记得回退
        }
    }
    cout << p->data;
}

HTML 1728 characters 221 words 102 paragraphs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值