题目描述
已知赫夫曼编码算法和程序,在此基础上进行赫夫曼解码
在赫夫曼树的类定义中增加了一个公有方法:
int Decode(const string codestr, char txtstr[]); //输入编码串codestr,输出解码串txtstr
该方法如果解码成功则返回1,解码失败则返回-1,本程序增加宏定义ok表示1,error表示-1
输入
第一行输入t,表示有t个测试实例
第二行先输入n,表示第1个实例有n个权值,接着输入n个权值,权值全是小于1万的正整数
第三行输入n个字母,表示与权值对应的字符
第四行输入k,表示要输入k个编码串
第五行起输入k个编码串
以此类推输入下一个示例
输出
每行输出解码后的字符串,如果解码失败直接输出字符串“error”,不要输出部分解码结果
输入样例1
2
5 15 4 4 3 2
A B C D E
3
11111
10100001001
00000101100
4 7 5 2 4
A B C D
3
1010000
111011
111110111
输出样例1
AAAAA
ABEAD
error
BBAAA
error
DCD
以下是思路
这题只需要在赫夫曼树的构建与编码的基础上添加一个Decode函数。需要变更的地方只有主函数和节点的构建和节点对应字符的初始化。(上一题数组访问是从1开始,所以huftree[i].weight = wei[i - 1]这块还是为i-1)。
class Node
{
public:
char data;//节点的对应字符
int left, right;
int weight;
int parent;
};
void HufTree::Init(int n, int* wei,char*str)
{
int i;
lnum = n;
len = 2 * n - 1;
huftree = new Node[2 * n];
code = new string[lnum + 1];
for (i = 1;i <= n;i++)
{
huftree[i].weight = wei[i - 1];
huftree[i].data = str[i - 1];//给节点的对应字符赋值
}
for (i = 1;i <= len;i++)
{
if (i > n)
{
huftree[i].weight = 0;
}
huftree[i].parent = 0;
huftree[i].left = 0;
huftree[i].right = 0;
}
Init();
}
至于新增的Decode函数,思路就是拿编码串codestr去和每个节点的对应的编码相匹配。可以用find函数也可以自己写kmp去匹配。这里用的find。
int HufTree::Decode(const string codestr, char txtstr[])
{
int len = codestr.length();
int pos = 0;
int j = 0;
for (int i = 0;i < len;)
{
int flag = 0;
for (int j = 1;j <= lnum;j++)
{
int index = codestr.find(code[j], i);
if (index == i)
{
flag = 1;
txtstr[pos] = huftree[j].data;
pos++;
i += code[j].length();
}
}
if (flag == 0)
{
return error;
}
}
if (pos != 0)
{
return ok;
}
else
{
return error;
}
}
这里我用的str.find(string code,int pos)函数。大致意思就是从str[pos]开始匹配code字符串,并返回第一次匹配到时对应位置的下标;如果没有找到则返回-1。例子如下
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string str, code;
cin >> str;
for (int i = 0;i < 2;i++)
{
cin >> code;
if (str.find(code) == -1)
{
cout << "Not found" << endl;
}
else
{
cout << "index= " << str.find(code) <<endl;
}
}
}
运行结果
GuanZhuSZTUXieXieMiao
DaZhuan
Not found
Zhu
index= 4
以下是代码
#include <iostream>
#include <cstring>
using namespace std;
#define ok 1;
#define error -1;
class Node
{
public:
char data;
int left, right;
int weight;
int parent;
};
class HufTree
{
public:
Node* huftree;
int max = 10000;
int len;
int lnum;
string *code;
void Init();
void Init(int n, int* wei,char*str);
void SelectMin(int pos, int* s0, int* s1);
void Coding();
int Decode(const string codestr, char tststr[]);
};
void HufTree::Init()
{
for (int i = lnum + 1;i <= len;i++)
{
int s0, s1;
SelectMin(i - 1, &s0, &s1);
huftree[s0].parent = huftree[s1].parent = i;
huftree[i].left = s0;
huftree[i].right = s1;
huftree[i].weight = huftree[s0].weight + huftree[s1].weight;
}
}
void HufTree::Init(int n, int* wei,char*str)
{
int i;
lnum = n;
len = 2 * n - 1;
huftree = new Node[2 * n];
code = new string[lnum + 1];
for (i = 1;i <= n;i++)
{
huftree[i].weight = wei[i - 1];
huftree[i].data = str[i - 1];
}
for (i = 1;i <= len;i++)
{
if (i > n)
{
huftree[i].weight = 0;
}
huftree[i].parent = 0;
huftree[i].left = 0;
huftree[i].right = 0;
}
Init();
}
void HufTree::SelectMin(int pos, int* s0, int* s1)
{
int w0, w1, i;
w0 = w1 = max;
*s0 = *s1 = 0;
for (i=1;i <= pos;i++)
{
if (w0 > huftree[i].weight && !huftree[i].parent)
{
w1 = w0;
*s1 = *s0;
w0 = huftree[i].weight;
*s0 = i;
}
else if (w1 > huftree[i].weight && !huftree[i].parent)
{
w1 = huftree[i].weight;
*s1 = i;
}
}
}
void HufTree::Coding()
{
char* tmp = new char[lnum];;
int i, c, f, start;
tmp[lnum - 1] = '\0';
for (i = 1;i <= lnum;i++)
{
start = lnum - 1;
for (c = i, f = huftree[i].parent;f != 0;c = f, f = huftree[f].parent)
{
if (huftree[f].left == c)
{
tmp[--start] = '0';
}
else
{
tmp[--start] = '1';
}
code[i] = tmp[start] + code[i];
}
}
delete[]tmp;
}
int HufTree::Decode(const string codestr, char txtstr[])
{
int len = codestr.length();
int pos = 0;
int j = 0;
for (int i = 0;i < len;)
{
int flag = 0;
for (int j = 1;j <= lnum;j++)
{
int index = codestr.find(code[j], i);
if (index == i)
{
flag = 1;
txtstr[pos] = huftree[j].data;
pos++;
i += code[j].length();
}
}
if (flag == 0)
{
return error;
}
}
if (pos != 0)
{
return ok;
}
else
{
return error;
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
int* weight = new int[n];
for (int i = 0;i < n;i++)
{
cin >> weight[i];
}
char* str = new char[n];
for (int i = 0;i < n;i++)
{
cin >> str[i];
}
HufTree tree;
tree.Init(n, weight,str);
tree.Coding();
int test;
cin >> test;
for (int i = 0;i < test;i++)
{
char* txtstr = new char[10];
for (int i = 0;i < 10;i++)
{
txtstr[i] = '-';
}
string codestr;
cin >> codestr;
if (tree.Decode(codestr, txtstr)==-1)
{
cout << "error" << endl;
}
else
{
for (int i = 0;i < 10;i++)
{
if (txtstr[i] != '-')
{
cout << txtstr[i];
}
else
{
break;
}
}
cout << endl;
}
}
delete[]weight;
}
}