typedef struct
{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
void HuffmanCoding(HuffmanTree &ht,HuffmanCode &hc,int *w,int n);
void Select(HuffmanTree ht,int n,int &s1,int &s2);
void HuffmanCoding(HuffmanTree &ht,HuffmanCode &hc,int *w,int n)
{
//w存放的是每个字符的权值,w的0号单位未用
//构造哈夫曼树ht,并求出n个字符的哈夫曼树编码hc
//初始化
if(n<=1)
return;
int m=2*n-1; //一棵有n个叶子结点的哈夫曼树共有2n-1个结点
ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); //0号单元未用
HuffmanTree p;
int i;
for(p=ht+1,i=1;i<=n;++i,++p) //每棵树只有带权值为w[i]的根,左右子树为空
{
p->weight=w[i];
p->parent=p->lchild=p->rchild=0;
}
for(;i<=m;i++,p++)
p->parent=p->lchild=p->rchild=p->weight=0;
int s1,s2;
//建立哈夫曼树
for(i=n+1;i<=m;i++)
{
//Select函数在已有的ht[1..i-1]中选择parent为0且weight最小的两个结点,赋值给s1、s2
Select(ht,i-1,s1,s2);
ht[s1].parent=ht[s2].parent=i;
ht[i].lchild=s1;
ht[i].rchild=s2;
ht[i].weight=ht[s1].weight+ht[s2].weight; //选取权值最小的树作为左右子树构造一棵新的二叉树
}
//从叶子到根逆向求每个字符的哈夫编码
hc=(HuffmanCode)malloc((n+1)*sizeof(char *));
char *cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++) //逐个字符求哈夫曼编码
{
int start=n-1;
int c,f;
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)); //为第i个字符编码分配空间
strcpy(hc[i],&cd[start]); //从cd复制到hc[i]中
}
}
void Select(HuffmanTree ht,int n,int &s1,int &s2)
{
int flag[n+1];
for(int i=0;i<n+1;i++)
flag[i]=0;
int temp,i,j;
//找出第一个parent为0且值最小的结点
for(i=1;i<=n;i++)
{
if(ht[i].parent==0)
{
temp=ht[i].weight;
j=i;
}
}
for(i=1;i<=n;i++)
{
if(temp>ht[i].weight&&ht[i].parent==0)
{
temp=ht[i].weight;
j=i;
}
}
s1=j;flag[j]=1;
//找出第二个parent为0且值最小的结点,不同于第一个
for(i=1;i<=n;i++)
{
if(ht[i].parent==0&&flag[i]==0)
{
temp=ht[i].weight;
j=i;
}
}
for(i=1;i<=n;i++)
{
if(temp>ht[i].weight&&flag[i]==0&&ht[i].parent==0)
{
temp=ht[i].weight;
j=i;
}
}
s2=j;flag[j]=1;
}
哈夫曼树以及哈夫曼编码的实现
最新推荐文章于 2021-05-16 03:30:08 发布