1.声明及建立
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
struct Node
{
int i,wei;
char c;
}node[20];
priority_queue<Node>pq1;
void HuffCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n,char *ger,char *tran)
{
int i,j,m,f;
Node s1,s2,s3;
HuffmanTree p;
if(n<=1) return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT+1,i=1;i<=m;++i,++p,++w) //从1开始,初始化
{
if(i<=n) {(*p).weight=*w;pq1.push(node[i]);}
else (*p).weight=0;
(*p).parent=0;
(*p).lchild=0;
(*p).rchild=0;
}
for(i=n+1;i<=m;++i)
{
s1=pq1.top();pq1.pop();
s2=pq1.top();pq1.pop();
s3.wei=s1.wei+s2.wei;
s3.i=i;
pq1.push(s3);
HT[s1.i].parent=i;HT[s2.i].parent=i;
HT[i].lchild=s1.i;HT[i].rchild=s2.i;
HT[i].weight=HT[s1.i].weight+HT[s2.i].weight;
}
}
重载优先队列:寻找两个最小的权值
bool operator <(const struct Node &A,const struct Node&B)
{
if(A.wei==B.wei) return A.i>B.i;
else return A.wei>B.wei;
}
2.编码
1)叶子到根逆向求编码
//******************叶子到根逆向求编码**************
HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
char *cd;
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;++i)
{
cd[n-1]='\0';
int start=n-1;
for(j=i,f=HT[i].parent;f!=0;j=f,f=HT[f].parent)//找到根结点退出
{
if(HT[f].lchild==j) cd[--start]='0';
else cd[--start]='1';
}
HC[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
printf("%c: %s\n",node[i].c,HC[i]);
}
printf("\n");
free(cd);
2)无栈非递归遍历求编码(顺序)
//******************无栈非递归遍历求编码**************
j=m;//
int cdlen=0;
for(i=1;i<=m;++i) HT[i].weight=0;//标记访问次数
while(j)
{
if(HT[j].weight==0)
{
HT[j].weight=1;
if(HT[j].lchild!=0) {j=HT[j].lchild;cd[cdlen++]='0';}//一直找到左孩子为空
else if(HT[j].rchild==0)//如果右孩子不存在,直接输出编码
{
HC[j]=(char *)malloc((cdlen+1)*sizeof(char));
cd[cdlen]='\0';strcpy(HC[j],cd);
printf("%c: %s\n",node[j].c,HC[j]);
}
}
else if(HT[j].weight==1)//找到访问一次的节点,如果右孩子存在,继续查找右子树 {
HT[j].weight=2;
if(HT[j].rchild!=0) {j=HT[j].rchild;cd[cdlen++]='1';}
}
else
{
HT[j].weight=0;j=HT[j].parent;--cdlen;//查找完后返回双亲
}
}
free(cd);
3.译码
//生成
int len=strlen(ger);
for(j=0;j<len;j++)
{
for(i=1;i<=n;i++)
{
if(node[i].c==ger[j])
cout<<HC[i]<<' ';
}
}cout<<endl;
//译码
char str[10];
int len1=strlen(tran),k;
for(j=0;j<len1;)
{
f=m;k=0;
memset(str,0,sizeof(str));
while(f)
{
if(HT[f].rchild&&tran[j]=='1')
{f=HT[f].rchild;str[k++]='1';}
else if(HT[f].lchild&&tran[j]=='0')
{f=HT[f].lchild;str[k++]='0';}
else
break;
j++;
}
for(i=1;i<=n;i++)
{
if(strcmp(HC[i],str)==0)
cout<<node[i].c<<' ';
}
}