//採用哈希的思想建哈夫曼樹
//0-9對應的數組地址1-10 A-Z對應的數組11-36 '_'則是37
//新生成的N-1課樹從38開始建立
#include<iostream>
#include<string.h>
#include<iomanip>
using namespace std;
int T[100][5];
void select(int &min,int &max)
{
int Min_val=9999999;
int Min_i;
for(int i=min;i<=max;i++)
if(T[i][0]<Min_val&&T[i][1]==0)//選擇沒父親的樹
{
Min_val=T[i][0];
Min_i=i;
}
int Max_i;
int Max_val=9999999;
for(int i=min;i<=max;i++)
{
if(i==Min_i)
continue;
if(T[i][0]<Max_val&&T[i][1]==0)
{
Max_val=T[i][0];
Max_i=i;
}
}
min=Min_i;
max=Max_i;
}
int main()
{
string n;
while(getline(cin,n),n!="END")
{
int lenth=n.size();
for(int i=1;i<100;i++)
{
T[i][1]=-1;T[i][0]=0;//所有結點的權重初始爲0,父親爲-1
}
for(int i=0;i<lenth;i++)
{
if(n[i]>='A'&&n[i]<='Z')
{
T[n[i]-54][0]++; T[n[i]-54][1]=0;
}
if(n[i]>='0'&&n[i]<='9')
{
T[n[i]-47][0]++;T[n[i]-47][1]=0;
}
if(n[i]=='_')
{
T[n[i]-58][0]++; T[n[i]-58][1]=0;
}
}
int sum=0;
for(int i=1;i<100;i++)
if(T[i][0])
sum++;
int flag=0;
if(sum==1)
flag=1;
int max=37;
int j=max;
int min=1;
while(j<=37+sum-2)
{
select(min,max);
T[j+1][0]=T[min][0]+T[max][0];//新的樹的權重等於兩個孩子的權重和
T[j+1][2]=min;T[j+1][3]=max;//新的樹的左右孩子的地址
T[j+1][1]=0;//新的樹的父親爲0
T[min][1]=j+1;T[max][1]=j+1; //左右子樹的父親爲 j+1
j++;
max=j;
min=1;
}
for(int i=1;i<=37;i++)
{
if(T[i][1]!=-1)
{
int j=i;
int temp=0;
while(T[j][1])
{
temp++;
j=T[j][1];
}
T[i][4]=temp;
}
}
sum=0;
for(int i=0;i<lenth;i++)
{
if(n[i]>='A'&&n[i]<='Z')
{
sum+=T[n[i]-54][4];
}
if(n[i]>='0'&&n[i]<='9')
{
sum+=T[n[i]-47][4];
}
if(n[i]=='_')
{
sum+=T[n[i]-58][4];
}
}
if(flag)
sum=lenth;
cout<<lenth*8<<" "<<sum<<" ";
cout<<fixed<<setprecision(1)<<(float)lenth*8/(float)sum<<endl;
}
return 0;
}
ACM--Entrophy(哈希+數組 建樹)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.