【问题描述】
给定一组字符的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