哈夫曼编/译码器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int MAXN=0x3f3f3f3f;
char* HC[120]; //指针的指针就全局处理,子函数就不用传,方便
struct HtNode
{
int weight;
int parent;
int Lchild;
int Rchild;
};
typedef struct HtTree
{
struct HtNode ht[120];
int root; //root在本到题中,没用
}HtTree,*PHtTree;
void select(PHtTree pht,int pos,int* x1,int* x2)
{
int m1=MAXN,m2=MAXN;
int j;
for(j=1;j<pos;j++)//pos=n+i,因为不包括自己,所以是<
{
if(pht->ht[j].weight<m1&&pht->ht[j].parent==0)
{
m2=m1;
*x2=*x1; //m2,x2都是存次小的
m1=pht->ht[j].weight;
*x1=j;
}
else if(pht->ht[j].weight<m2&&pht->ht[j].parent==0)
{
m2=pht->ht[j].weight;
*x2=j;
}
}
return;
}
PHtTree CreateHuffmanTree(int w[],int n)//ht就是huffmantree的缩写。
{
PHtTree pht;
int i,x1,x2;
pht=(PHtTree)malloc(sizeof(HtTree));
for(i=1;i<=2*n-1;i++)
{
pht->ht[i].parent=0;
pht->ht[i].Lchild=0;
pht->ht[i].Rchild=0;
if(i<=n)
pht->ht[i].weight=w[i];
else
pht->ht[i].weight=0; //一开始所有结点的双亲,子女都为0;
}
for(i=1;i<n;i++)
{
select(pht,n+i,&x1,&x2); //因为不能返回两个值,所以只能用指针写。
pht->ht[x1].parent = n + i;
pht->ht[x2].parent = n + i;
pht->ht[n+i].weight = pht->ht[x1].weight
+ pht->ht[x2].weight;
pht->ht[n+i].Lchild = x1;
pht->ht[n+i].Rchild = x2;
pht->root = n+i; //由上而下,逐层建立头结点。
}
return pht;
}
void CreHuffmanCode(PHtTree pht,int n) //n就是n个叶子结点
{
char *cd;
cd=(char*)malloc(n*sizeof(char)); //因为编码最长也不过log2n;所以长度足够了。
cd[n-1]='\0';//从右往左逐位存放编码,首先存放编码结束符
int i,c,p,start;
for(i=1;i<=n;i++)
{
start=n-1;
c=i;p=pht->ht[i].parent; //提取parent很重要哦。
while(p!=0)
{
--start; //因为之前cd[n-1]='\0'了,所以一进来,start就要减1;
if(pht->ht[p].Lchild==c)
cd[start]='0';//再次强调是从右往左逐位存放编码
else
cd[start]='1';
c=p;p=pht->ht[p].parent;//向上推。
} //这样就把i的编码给编出来了。
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]); //注意啊,是取start为下标的地址。所以个数是恰好匹配的
}
free(cd);
return;
}
int main()
{
int n,i;
PHtTree pht;
char s[120];
char sss[120];
int w[120];
scanf("%d",&n);
getchar();//后面是字符型,所以要吸收这个空格
for(i=1;i<=n;i++)
scanf("%c ",&s[i]);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
getchar();
gets(sss);
pht=CreateHuffmanTree(w,n);
CreHuffmanCode(pht,n);
int len=strlen(sss);
for(i=0;i<len;i++)
{
printf("%s",HC[sss[i]-'a'+1]);
}
printf("\n");
printf("%s",sss);
return 0;
}