/*
注:输入为多行字符串,以“0”结尾;例:abc def 0
此程序无法执行由单个字符组成的字符串。
*/
#include<iostream>
#include<string>
#include<map>
using namespace std;
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
void Select(HuffmanTree HT,int len,int &s1,int &s2)
{
int i,min1=0x3f3f3f3f,min2=0x3f3f3f3f;//先赋予最大值
for(i=1;i<=len;i++)
{
if(HT[i].weight<min1&&HT[i].parent==0)
{
min1=HT[i].weight;
s1=i;
}
}
int temp=HT[s1].weight;//将原值存放起来,然后先赋予最大值,防止s1被重复选择
HT[s1].weight=0x3f3f3f3f;
for(i=1;i<=len;i++)
{
if(HT[i].weight<min2&&HT[i].parent==0)
{
min2=HT[i].weight;
s2=i;
}
}
HT[s1].weight=temp;//恢复原来的值
}
//用算法5.10构造赫夫曼树
void CreatHuffmanTree(HuffmanTree &HT,int n,map<char,int> & maps)
{
//构造赫夫曼树HT
int m,s1,s2,i;
if(n<=1) return;
m=2*n-1;
HT=new HTNode[m+1]; //0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根结点
for(i=1;i<=m;++i) //将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0
{ HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; }
map<char,int>::iterator it;
it=maps.begin();
for(i=1;i<=n;++i,it++) //输入前n个单元中叶子结点的权值
HT[i].weight=it->second;
/*――――――――――初始化工作结束,下面开始创建赫夫曼树――――――――――*/
for(i=n+1;i<=m;++i)
{ //通过n-1次的选择、删除、合并来创建赫夫曼树
Select(HT,i-1,s1,s2);
//在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值最小的结点,
// 并返回它们在HT中的序号s1和s2
HT[s1].parent=i;
HT[s2].parent=i;
//得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为i
HT[i].lchild=s1;
HT[i].rchild=s2 ; //s1,s2分别作为i的左右孩子
HT[i].weight=HT[s1].weight+HT[s2].weight; //i 的权值为左右孩子权值之和
} //for
}
// CreatHuffmanTree
void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{
//从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中
int i,start,c,f;
HC=new char*[n+1]; //分配n个字符编码的头指针矢量
char *cd=new char[n]; //分配临时存放编码的动态数组空间
cd[n-1]='\0'; //编码结束符
for(i=1;i<=n;++i)
{ //逐个字符求赫夫曼编码
start=n-1; //start开始时指向最后,即编码结束符位置
c=i;
f=HT[i].parent; //f指向结点c的双亲结点
while(f!=0)
{ //从叶子结点开始向上回溯,直到根结点
--start; //回溯一次start向前指一个位置
if(HT[f].lchild==c)
cd[start]='0'; //结点c是f的左孩子,则生成代码0
else
cd[start]='1'; //结点c是f的右孩子,则生成代码1
c=f;
f=HT[f].parent; //继续向上回溯
} //求出第i个字符的编码
HC[i]=new char[n-start]; // 为第i 个字符编码分配空间
strcpy(HC[i], &cd[start]); //将求得的编码从临时空间cd复制到HC的当前行中
}
delete cd; //释放临时空间
}
void select_yuan_su(string a1,map<char,int> & maps,int &n,string &h)
{
map<char,int>::iterator it,is;
for(int i=0;i<a1.length();i++)
{
it = maps.find(a1[i]);
if(it != maps.end())
(it->second)++;
else
{ maps[ a1[i] ] = 1; n++;}
}
is=maps.end();
is--;
for(it=maps.begin();it!=maps.end();it++)
{
h+=it->first;
cout<<it->first<<":"<<it->second;
if(it!=is) cout<<" ";
}
cout<<endl;
}
void shuchu_zhongtai(HuffmanTree ht,int n)
{
for(int i=1;i<2*n;i++)
{
cout<<i<<" "<<ht[i].weight<<" "<<ht[i].parent
<<" "<<ht[i].lchild<<" "<<ht[i].rchild<<endl;
}
}
void shuchu_bian_ma(HuffmanCode hc,int n,map<char,int> &maps)
{
map<char,int>::iterator it,is;
it=maps.begin();
is=maps.end();
is--;
for(int i=1;i<=n;++i,it++)
{
cout<<it->first<<":"<<hc[i];
if(it!=is) cout<<" ";
}
cout<<endl;
}
string bian_ma(string a1,string h,HuffmanCode hc,int n)
{
string m;
char m2;
for(int i=0;i<a1.length();i++)
{
m2=a1[i];
for(int j=0;j<n;j++)
{
if(m2==h[j])
{
m+=hc[j+1];
break;
}
}
}
cout<<m<<endl;
return m;
}
void jie_ma(string m,string h,HuffmanCode hc,int n)
{
string y,x;
for(int i=0;i<m.length();i++)
{
y+=m[i];
for(int j=1;j<=n;j++)
{
if(y==hc[j])
{
x+=h[j-1];
y.erase();
break;
}
}
}
cout<<x<<endl;
}
void main()
{
string a1;
string b1="0";
cin>>a1;
while(a1!=b1)
{
map<char,int> maps;
int i,n;
string h;
n=0;
select_yuan_su(a1,maps,n,h);
HuffmanTree ht;
HuffmanCode hc;
CreatHuffmanTree(ht,n,maps);
shuchu_zhongtai(ht,n);
CreatHuffmanCode(ht,hc,n);
shuchu_bian_ma(hc,n,maps);
string m=bian_ma(a1,h,hc,n);
jie_ma(m,h,hc,n);
cin>>a1;
}
}