问题描述
给定一组字符的Huffman编码表(从标准输入读取),以及一个用该编码表进行编码的Huffman编码文件(存在当前目录下的in.txt中),编写程序实现对Huffman编码文件的解码,并按照前序遍历序列输出解码过程中Huffman树(规定树中左分支表示0,右分支表示1)中各结点的访问次数。
例如给定的一组字符的Huffman编码表为:
6
1:111
2:0
+:110
*:1010
=:1011
8:100
第一行的6表示要对6个不同的字符进行编码,后面每行中冒号(:)左边的字符为待编码的字符,右边为其Huffman编码,冒号两边无空格。对于该编码表,对应的Huffman树(树中左分支表示0,右分支表示1)应为:
假如Huffman编码文件in.txt中的内容(由0和1字符组成的序列)为:
111011001010011001011111100
则遍历上述Huffman树即可对该文件进行解码,解码后的文件内容为:
12+2*2+2=18
解码过程中,经过Huffman树中各结点的遍历次数见下图中结点中的数字:
对该Huffman树中各结点的访问次数按照前序遍历序列输出应为:
11 4 7 3 1 2 1 1 4 2 2
输入形式
先从标准输入读入待编码的字符个数(大于等于2,小于等于50),然后分行输入各字符的Huffman编码(先输入字符,再输入其编码,字符和编码中间以一个英文字符冒号:分隔),编码只由0和1组成。
Huffman编码文件为当前目录下的in.txt文本文件,即:其中的0和1都是以单个字符的形式存储,文件末尾有一个回车换行符。
输出形式
先将解码后的文件内容输出到标准输出上(独占一行);然后以前序遍历序列输出解码过程中Huffman树中各结点的访问次数,各数据间以一个空格分隔,最后一个数据后也有一个空格。
样例输入
6
1:111
2:0
+:110
*:1010
=:1011
8:100
假如in.txt中的内容为:
111011001010011001011111100
样例输出
12+2*2+2=18
11 4 7 3 1 2 1 1 4 2 2
样例说明
从标准输入读取了6个字符的Huffman编码,因为规定Huffman树中左分支表示0,右分支表示1,所以利用该编码表可构造上述Huffman树(见图1)。遍历该Huffman树对编码文件in.txt的进行解码,即可得到解码后的原文件内容,遍历过程中各树中结点的最终访问次数要按照前序遍历序列输出。
代码
#include <iostream>
#include<fstream>
#include <vector>
using namespace std;
typedef struct TreeNode {
int count;
char data;
TreeNode* lchild;
TreeNode* rchild;
}TreeNode;
TreeNode* CreatNode(TreeNode* node, char i) {
if (i == '1') {
if (node->rchild == NULL) {
node->rchild = new TreeNode();
node->rchild->count = 0;
}
node = node->rchild;
}
else if (i == '0') {
if (node->lchild == NULL) {
node->lchild = new TreeNode();
node->lchild->count = 0;
}
node = node->lchild;
}
return(node);
};
void CreatTree(TreeNode *root) {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
TreeNode *temp = root;
char c,c1;
cin >> c>>c1;
string str;
cin >> str;
for (int j = 0; j < str.size(); j++) {
temp = CreatNode(temp,str[j]);
}
temp->data = c;
}
}
string Readfile() {
ifstream fin;
fin.open("in.txt");
string str="";
if (!fin.is_open()) {
cout << "ERROR";
return str;
}
while (!fin.eof()) {
fin >> str;
}
fin.close();
return str;
}
void Decode(string s,TreeNode * root) {
TreeNode* temp = root;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '0') {
temp->count++;
temp = temp->lchild;
}
else if (s[i] == '1') {
temp->count++;
temp = temp->rchild;
}
if (temp->data != '\0') {
cout << temp->data;
temp->count++;
temp = root;
}
}
cout << endl;
}
void PreOrderTravel(TreeNode* root)
{
if (root == NULL)
return;
cout << root->count<<" ";
PreOrderTravel(root->lchild);
PreOrderTravel(root->rchild);
}
void Delete(TreeNode* root)
{
if (root == NULL)
return;
Delete(root->lchild);
Delete(root->rchild);
delete(root);
}
int main()
{
TreeNode* root = new TreeNode;
root->count = 0;
root->data = '\0';
root->lchild = NULL;
root->rchild = NULL;
CreatTree(root);
string s=Readfile();
Decode(s,root);
PreOrderTravel(root);
Delete(root);
}