#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MaxW=9999;
class HuffNode
{
public:
int weight;
char name;
int parent;
int lchild;
int rchild;
};
class HuffMan
{
private:
void MakeTree()
{
int i,s1,s2;
for(i=lnum+1;i<=len;i++)
{
SelectMin(i-1,&s1,&s2);//找出权值最小的两个节点
huffTree[s1].parent=i;//权值最小的两个节点的父节点从n+1开始
huffTree[s2].parent=i;
huffTree[i].lchild=s1;//父节点左右孩子分别是这两个最小的权值的指针值
huffTree[i].rchild=s2;
huffTree[i].weight=huffTree[s1].weight+huffTree[s2].weight;//父节点的权值是这两个最小的节点的权值之和
}
}
void SelectMin(int pos,int *s1,int *s2)//找出最小权值的的两个节点,并把他们的指针值赋给s1,s2
{
int w1,w2,i;
w1=MaxW;w2=MaxW;
*s1=0;*s2=0;
for(i=1;i<=pos;i++)
{
if(huffTree[i].weight<w1 && huffTree[i].parent==0)//w1比w2小,所以出现有比w1小的权值时,s1的指针值赋给s2,w1的权值赋给w2
{ //一定要注意父节点的值为0是条件,是为了排除已经找出的最小权值的节点重新进行排序
*s2=*s1;w2=w1;
*s1=i;
w1=huffTree[i].weight;//然后将该指针值赋给s1,并把权值赋给w1
}
else if(huffTree[i].weight<w2 && huffTree[i].parent==0)//出现比w1大比w2小的权值时,直接将该指针值赋给s2,并把权值赋给w2
{
*s2=i;
w2=huffTree[i].weight;
}
}
}
public:
int len;
int lnum;
HuffNode *huffTree;
string *huffCode;//存放编码的string指针
void MakeTree(int n,int wt[],char name[])//传入叶子节点的数量,权值,和名字
{
int i;
lnum=n;
len=2*n-1;//节点的数量是2*n-1
huffTree = new HuffNode[2*n];//给结构体指针huffTree分配大小为2*n大小的空间
huffCode = new string[lnum+1];//给哈夫曼的编码string指针分配n+1de大小空间
for(i=1;i<=n;i++)//注意是下标是从1开始的
{
huffTree[i].weight=wt[i-1];//初始化叶子结点的权值和名字
huffTree[i].name=name[i-1];
}
for(i=1;i<=len;i++)
{
if(i>n) huffTree[i].weight=0;//初始化化其他节点的权值为0
huffTree[i].parent=0;//初始化所有节点的父节点,左右孩子的指针值为0
huffTree[i].lchild=0;
huffTree[i].rchild=0;
}
MakeTree();//初始化其他节点的父节点,左右孩子,和权值
}
void Coding()
{
char *cd;
int i,c,f,start;
cd=new char[lnum];//存放编码的字符数组
cd[lnum-1]='\0';
for(i=1;i<=lnum;++i)
{
start=lnum-1;//c是自节点,f是父节点,循环就是子节点变为父节点,父节点变为父节点的父节点,依次类推
for(c=i,f=huffTree[i].parent;f!=0;c=f,f=huffTree[f].parent)//先依次找到叶子节点的父节点,然后再判断是父节点的左孩子,还是右孩子
if(huffTree[f].lchild==c) cd[--start]='0';//直到节点的父节点为0
else cd[--start]='1';
huffCode[i].assign(&cd[start]);//将字符编码存放到字符编码的指针
}
delete []cd;
}
void display(char str[])
{
int len=strlen(str);
for(int i=0;i<len;i++)
{
for(int j=0;j<=lnum;j++)
{
if(str[i]==huffTree[j].name)
cout<<huffCode[j];
}
}
cout<<endl;
}
int Decode(const string codestr,char txtstr[])
{
int i,k,c;
char ch;
c=len;//从最大的父节点开始
k=0;
for(i=0;i<codestr.length();i++)
{
ch=codestr[i];
if(ch=='0') c=huffTree[c].lchild;//如果是0的话,子节点变为当前节点的左节点
if(ch=='1') c=huffTree[c].rchild;//如果是1的话,子节点变为当前节点的右节点
if(ch!='0'&&ch!='1') return -1;
if(huffTree[c].lchild==0 && huffTree[c].rchild==0)//当找到叶子节点时候
{
txtstr[k]=huffTree[c].name;//将叶子节点的名字赋给解编码的数组
k++;
c=len;//每次找到一个叶子节点,都要回到最大的父节点
}
else ch='\0';
}
if(ch=='\0') return -1;
else txtstr[k]='\0';
return 1;
}
void Destroy()
{
len=0;
lnum=0;
delete []huffTree;
delete []huffCode;
}
};
int main()
{
int t,n,i,j;
char name[100];
int wt[800];
string str;
char Name[1000];
HuffMan myHuff,myHuff1;
cin>>t;
for(i=0;i<t;i++)
{
cin>>n;
for(j=0;j<n;j++)
cin>>name[j];
for(j=0;j<n;j++)
cin>>wt[j];
myHuff.MakeTree(n,wt,name);
myHuff.Coding();
cin>>Name;
cin>>str;
char ch[800];
int m=myHuff.Decode(str,ch);
for(j=1;j<=n;j++)
{
cout<<myHuff.huffTree[j].name<<" :";
cout<<myHuff.huffCode[j]<<endl;
}
myHuff.display(Name);
if(m==-1) cout<<"error!"<<endl;
if(m==1) cout<<ch<<endl;
myHuff.Destroy();
}
return 0;
}
#include<string>
#include<cstring>
using namespace std;
const int MaxW=9999;
class HuffNode
{
public:
int weight;
char name;
int parent;
int lchild;
int rchild;
};
class HuffMan
{
private:
void MakeTree()
{
int i,s1,s2;
for(i=lnum+1;i<=len;i++)
{
SelectMin(i-1,&s1,&s2);//找出权值最小的两个节点
huffTree[s1].parent=i;//权值最小的两个节点的父节点从n+1开始
huffTree[s2].parent=i;
huffTree[i].lchild=s1;//父节点左右孩子分别是这两个最小的权值的指针值
huffTree[i].rchild=s2;
huffTree[i].weight=huffTree[s1].weight+huffTree[s2].weight;//父节点的权值是这两个最小的节点的权值之和
}
}
void SelectMin(int pos,int *s1,int *s2)//找出最小权值的的两个节点,并把他们的指针值赋给s1,s2
{
int w1,w2,i;
w1=MaxW;w2=MaxW;
*s1=0;*s2=0;
for(i=1;i<=pos;i++)
{
if(huffTree[i].weight<w1 && huffTree[i].parent==0)//w1比w2小,所以出现有比w1小的权值时,s1的指针值赋给s2,w1的权值赋给w2
{ //一定要注意父节点的值为0是条件,是为了排除已经找出的最小权值的节点重新进行排序
*s2=*s1;w2=w1;
*s1=i;
w1=huffTree[i].weight;//然后将该指针值赋给s1,并把权值赋给w1
}
else if(huffTree[i].weight<w2 && huffTree[i].parent==0)//出现比w1大比w2小的权值时,直接将该指针值赋给s2,并把权值赋给w2
{
*s2=i;
w2=huffTree[i].weight;
}
}
}
public:
int len;
int lnum;
HuffNode *huffTree;
string *huffCode;//存放编码的string指针
void MakeTree(int n,int wt[],char name[])//传入叶子节点的数量,权值,和名字
{
int i;
lnum=n;
len=2*n-1;//节点的数量是2*n-1
huffTree = new HuffNode[2*n];//给结构体指针huffTree分配大小为2*n大小的空间
huffCode = new string[lnum+1];//给哈夫曼的编码string指针分配n+1de大小空间
for(i=1;i<=n;i++)//注意是下标是从1开始的
{
huffTree[i].weight=wt[i-1];//初始化叶子结点的权值和名字
huffTree[i].name=name[i-1];
}
for(i=1;i<=len;i++)
{
if(i>n) huffTree[i].weight=0;//初始化化其他节点的权值为0
huffTree[i].parent=0;//初始化所有节点的父节点,左右孩子的指针值为0
huffTree[i].lchild=0;
huffTree[i].rchild=0;
}
MakeTree();//初始化其他节点的父节点,左右孩子,和权值
}
void Coding()
{
char *cd;
int i,c,f,start;
cd=new char[lnum];//存放编码的字符数组
cd[lnum-1]='\0';
for(i=1;i<=lnum;++i)
{
start=lnum-1;//c是自节点,f是父节点,循环就是子节点变为父节点,父节点变为父节点的父节点,依次类推
for(c=i,f=huffTree[i].parent;f!=0;c=f,f=huffTree[f].parent)//先依次找到叶子节点的父节点,然后再判断是父节点的左孩子,还是右孩子
if(huffTree[f].lchild==c) cd[--start]='0';//直到节点的父节点为0
else cd[--start]='1';
huffCode[i].assign(&cd[start]);//将字符编码存放到字符编码的指针
}
delete []cd;
}
void display(char str[])
{
int len=strlen(str);
for(int i=0;i<len;i++)
{
for(int j=0;j<=lnum;j++)
{
if(str[i]==huffTree[j].name)
cout<<huffCode[j];
}
}
cout<<endl;
}
int Decode(const string codestr,char txtstr[])
{
int i,k,c;
char ch;
c=len;//从最大的父节点开始
k=0;
for(i=0;i<codestr.length();i++)
{
ch=codestr[i];
if(ch=='0') c=huffTree[c].lchild;//如果是0的话,子节点变为当前节点的左节点
if(ch=='1') c=huffTree[c].rchild;//如果是1的话,子节点变为当前节点的右节点
if(ch!='0'&&ch!='1') return -1;
if(huffTree[c].lchild==0 && huffTree[c].rchild==0)//当找到叶子节点时候
{
txtstr[k]=huffTree[c].name;//将叶子节点的名字赋给解编码的数组
k++;
c=len;//每次找到一个叶子节点,都要回到最大的父节点
}
else ch='\0';
}
if(ch=='\0') return -1;
else txtstr[k]='\0';
return 1;
}
void Destroy()
{
len=0;
lnum=0;
delete []huffTree;
delete []huffCode;
}
};
int main()
{
int t,n,i,j;
char name[100];
int wt[800];
string str;
char Name[1000];
HuffMan myHuff,myHuff1;
cin>>t;
for(i=0;i<t;i++)
{
cin>>n;
for(j=0;j<n;j++)
cin>>name[j];
for(j=0;j<n;j++)
cin>>wt[j];
myHuff.MakeTree(n,wt,name);
myHuff.Coding();
cin>>Name;
cin>>str;
char ch[800];
int m=myHuff.Decode(str,ch);
for(j=1;j<=n;j++)
{
cout<<myHuff.huffTree[j].name<<" :";
cout<<myHuff.huffCode[j]<<endl;
}
myHuff.display(Name);
if(m==-1) cout<<"error!"<<endl;
if(m==1) cout<<ch<<endl;
myHuff.Destroy();
}
return 0;
}