#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
struct Node
{
int lc,rc,pa;
int val;
int pos;
char s[20];
char str;
}a[10000];
bool operator> (const Node& x, const Node &y)
{
return x.val > y.val;
}
void init(int n)
{
int i;
for(i=n+1;i<=n*2-1;i++)
a[i].lc=a[i].rc=a[i].pa=-1,a[i].pos=i,a[i].val=0;
}
char ss[1000];
int vis[1000],Sum;
void build(int x,int level)
{
if(a[x].lc!=-1)
{
ss[level]='0';
build(a[x].lc,level+1);
}
if(a[x].rc!=-1)
{
ss[level]='1';
build(a[x].rc,level+1);
}
if(a[x].lc==a[x].rc)
{
ss[level]='/0';
strcpy(a[x].s,ss);
}
}
void search(char s[],int n)
{
if(a[n].lc==a[n].rc)
{
cout<<a[n].str;
return ;
}
int k=Sum++;
if(s[k]=='1')
{
search(s,a[n].rc);
return;
}
else if(s[k]=='0')
search(s,a[n].lc);
return;
}
int find(int c,char Str[],int cnt)
{
int count=0;
Sum=0;
while(Sum<c)
{
search(Str,cnt);
if(cnt==1) Sum++;
count++;
}
return count;
}
int main()
{
char str[10000],Str[10000];
int len,cnt=0,i,j;
cout<<"请输入要转变的字符串:/n";
cin.getline(str,1000);
priority_queue<Node, vector<Node>,greater<vector<Node>::value_type> > Q;
memset(vis,0,sizeof vis);
len=strlen(str);
for(i=0;i<len;i++)
{
if(!vis[str[i]])
{
vis[str[i]]=++cnt;
a[cnt].val=1;
a[cnt].str=str[i];
a[cnt].lc=a[cnt].rc=a[cnt].pa=-1;
a[cnt].pos=cnt;
}
else a[vis[str[i]]].val++;
}
init(cnt);
cout<<"每个字符出现的次数:/n";
for(i=1;i<=cnt;i++)
{
Q.push(a[i]);
printf("%c:%02d/t",a[i].str,a[i].val);
if(i%4==0) cout<<endl;
}
if(cnt%4!=0) cout<<endl;
int x,y,sum=cnt;
for(i=1;i<sum;i++)
{
x=Q.top().pos;//cout<<a[x].val<<endl;
Q.pop();
y=Q.top().pos;//cout<<a[y].val<<endl;
Q.pop();
cnt++;
a[cnt].val=a[x].val+a[y].val;
a[cnt].lc=x;a[cnt].rc=y;
a[x].pa=cnt;a[y].pa=cnt;
Q.push(a[cnt]);
}
build(cnt,0);
cout<<"树构造: "<<endl;
for(i=1;i<=cnt;i++)
printf("(%02d) father:%02d leftchild:%02d rightchild:%02d val:%d/n",i,a[i].pa,a[i].lc,a[i].rc,a[i].val);
puts("每个字符转换的代码:");
if(cnt==1) a[1].s[0]='0',a[1].s[1]=0;
for(i=1;i<=sum;i++)
printf("%c:%s/n",a[i].str,a[i].s);
printf("按回车键的得到编码:");getchar();
int c=0;
for(i=0;i<len;i++)
{
for(j=0;j<strlen(a[vis[str[i]]].s);j++)
Str[c++]=a[vis[str[i]]].s[j];
}
str[c]='/0';
for(i=0;i<c;i++)
cout<<Str[i];
cout<<endl;
//cout<<Str<<endl;
printf("按回车键的得到该码译码:");getchar();
find(c,Str,cnt);
puts("");
printf("原代码长度:%d/n压缩代码长度:%d/n压缩比为:%.1lf%%/n",len*8,c,(double)(c)/(len*8)*100);
printf("输入要翻译的代码数量:");
int num;
cin>>num;
for(i=1;i<=num;i++)
{
cin>>Str;
c=strlen(Str);
cout<<"原码为:";
len=find(c,Str,cnt);
puts("");
printf("原代码长度:%d/n压缩代码长度:%d/n压缩比为:%.1lf%%/n",len*8,c,(double)(c)/(len*8)*100);
}
return 0;
}