这是本人参考教材以后完成的,感觉这题难度不算很大,但是需要注意的细节较为多一点。
#include <iostream>
#include <string>
#define N 100 //字符集大小最多为100个
#define M 2*N-1 //最多产生的节点个数
#define max_weight 10000 //设置的最大权值
using namespace std;
typedef struct //定义哈夫曼树的结构体变量
{
int weight;
int parent;
int LChild;
int RChild;
}HuffmanTree;
HuffmanTree ht[M+1]; //弃用第0号位置,装载哈夫曼树的各节点
int coders[500]={0}; //装载对报文的编码
char decoders[100]; //装载对编码解码后的报文
char chars[100]; //装载输入的报文
int x=0,y=0;
void select(int w, int *s1, int *s2) //在当前所有没有双亲节点的节点中找到权值最小的两个节点,分别给s1(最小),s2(次小)
{
int i,j,t,flag;
int min_weight;
min_weight = max_weight;
for(i=1;i<=w;i++) //最小无双亲节点的节点的权值赋给s1
{
if(ht[i].parent!=0)
continue;
flag=ht[i].weight;
if(flag<min_weight)
{
min_weight = flag;
j=i;
}
}
*s1 = j;
min_weight = max_weight; //次小的无双亲节点的节点的权值赋给s2
for(i=1;i<=w;i++)
{
if(i==j)
continue;
if(ht[i].parent!=0)
continue;
flag=ht[i].weight;
if(flag<min_weight)
{
min_weight = flag;
t=i;
}
}
*s2 = t;
}
void CrtHuffmanTree( int w[], int n) //创建哈夫曼树
{
int m,i;
int s1,s2;
for(i=1;i<=n;i++) //对哈夫曼树初始化
ht[i]={w[i],0,0,0};
m=2*n-1;
for(i=n+1;i<=m;i++)
ht[i]={0,0,0,0};
for(i=n+1;i<=m;i++)
{
select(i-1,&s1,&s2); //挑选权值最小的节点编号,赋给s1,挑选次小的,赋给s2
ht[i].weight=ht[s1].weight+ht[s2].weight;
ht[s1].parent=i;
ht[s2].parent=i;
ht[i].LChild=s1;
ht[i].RChild=s2;
}
}
void transmit(char chars[], string code, int num[], int n, int m) //将目标报文按照给定的字符对应关系转化为数组
{
int i,j;
for(i=0;i<m;i++) //遍历目标报文的每一个字符
{
for(j=1;j<=n;j++) //查找字符与数字的对应关系,然后转化为数字
{
if(code[i]==chars[j])
{
num[i]=j;
break;
}
}
}
}
void CrtHuffmanCode(int num) //对报文每一个字符(已转化为数字)进行编码
{
int i,c,p,w=0;
int cd[100];
c=num;p=ht[num].parent;
while(p!=0)
{
if(ht[p].LChild==c)
cd[w++]=0;
else
cd[w++]=1;
c=p;
p=ht[p].parent;
}
for(i=w-1;i>=0;i--)
coders[x++]=cd[i];
}
void Decoder(int *t,int m) //对目标编码进行解码,得到解码后的报文
{
int c;
if(coders[(*t)++]==0)
c=ht[m].LChild;
else
c=ht[m].RChild;
while(ht[c].LChild!=0&&ht[c].RChild!=0)
{
if(coders[(*t)++]==0)
c=ht[c].LChild;
else
c=ht[c].RChild;
}
decoders[y++]=chars[c];
}
int main()
{
int i,m,n,t;
int weights[100],num[100];
string code;
cin>>n;
for(i=1;i<=n;i++)
cin>>chars[i];
for(i=1;i<=n;i++)
cin>>weights[i];
cin>>code;
m=code.size(); //报文长度
CrtHuffmanTree(weights, n); //构建哈夫曼树
transmit(chars,code,num,n,m); //将报文按照对应关系转化为数组
for(i=0;i<m;i++)
CrtHuffmanCode(num[i]); //对转化成数组的报文编码
for(t=0;t<x;)
Decoder(&t,2*n-1); //将已知编码解码成报文
for(i=0;i<x;i++)
cout<<coders[i]; //输出编码后的密码
cout<<endl;
for(i=0;i<y;i++)
cout<<decoders[i]; //输出解码后的报文
cout<<endl;
return 0;
}