# include <stdio.h>
# include <iostream>
# include <string.h>
using namespace std;
typedef struct //define structure HuffmanTree
{ int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char ** HuffmanCode;
void Select(HuffmanTree HT,int i,int &s1,int &s2) ;//选出HT树到i为止,权值最小且parent为0的2个节点
void HuffmanTreeing(HuffmanTree &HT,int *w,int n);//构建哈夫曼树函数
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n); //建立哈夫曼树编码
void output(HuffmanTree HT,int m);//输出哈夫曼树
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int n,i;
int *w;
scanf("%d",&n);
w=(int *)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
scanf("%d",&w[i]);
}
HuffmanTreeing( HT , w ,n );
HuffmanCoding( HT, HC ,n );
cout<<"哈夫曼编码:"<<endl;
for(i=1;i<=n;i++)
{
printf("HT[%d] node's Huffman code is: %s\n",i,HC[i]);
}
return 0;
}
void Select(HuffmanTree HT,int i,int &s1,int &s2)
{ //选出HT树到i为止,权值最小且parent为0的2个节点
//s1 is the least of HT[].weight
//s2 is the second least of HT[].weight
int j,k=1;
while(HT[k].parent!=0)
k++;
s1=k;
for(j=1; j<=i ;++j)
if(HT[j].parent==0 && HT[j].weight < HT[s1].weight )
s1=j;
k=1;
while( HT[k].parent!=0|| k==s1 )
k++;
s2=k;
for(j=1;j<=i;++j)
if( HT[j].parent==0 && HT[j].weight<HT[s2].weight && j!=s1)
s2=j;
}
void HuffmanTreeing(HuffmanTree &HT,int *w,int n) //构建哈夫曼树函数
{ // w存放n个字符的权值(均>0),构造赫夫曼树HT
int m,i,s1,s2;
if(n<=1)
return;
m= 2*n-1 ;
HT=(HuffmanTree) malloc( (m+1)*sizeof( HTNode ) );
for( i=1; i<=n; ++i ) //initial HT[1...n]
{
HT[i].weight= w[i-1] ;
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for( ; i<=m; ++i ) //initial HT[n+1...2*n1]
{
HT[i].weight = 0;
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for( i=n+1; i<=m; ++i )
{
Select(HT,i-1,s1,s2); // 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
HT[s1].parent= i ;
HT[s2].parent= i ;
HT[i].lchild= s1 ;
HT[i].rchild= s2 ;
HT[i].weight= HT[s1].weight+HT[s2].weight ;
}
}
void HuffmanCoding(HuffmanTree HT,HuffmanCode &HC,int n) //建立哈夫曼树编码
{ // 根据赫夫曼树HT,求出n个字符的赫夫曼编码HC
/********** Begin **********/
char *cd;
int i,start;
unsigned c,f;
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++){
start=n-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
if(HT[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
free(cd);
/********** End **********/
}
void output(HuffmanTree HT,int m)
{ //输出哈夫曼树
for(int i=1;i<=m;++i)
{
cout<<"HT["<<i<<"] ="<<HT[i].weight<<"\t"<<HT[i]. parent<<"\t";
cout<<"\t" <<HT[i]. lchild <<"\t" <<HT[i]. rchild<<endl;
}
}