思路
- 构建哈弗曼树同自底向上,编码时用weight标识访问状态即可。
注意
代码
#include<algorithm>
#include<cstring>
using namespace std;
struct HTNode{
int lchild,rchild,parent;
int weight;
};
const int maxn=101;
int w[maxn];
int n;
void select(HTNode *HT,int n,int& s1,int &s2){
int m=0xfffffff;
for(int i=1;i<=n;i++){
if(HT[i].weight<m&&HT[i].parent==0){
s1=i;
m=HT[i].weight;
}
}
m=0xfffffff;
for(int i=1;i<=n;i++){
if(HT[i].weight<m&&HT[i].parent==0&&i!=s1){
s2=i;
m=HT[i].weight;
}
}
if(s1>s2) swap(s1,s2);
}
void HuffmanCoding(HTNode *HT,char **&HC,int w[],int n){
if(n<=1) return;
int m=2*n-1;
int s1,s2;
HT=new HTNode[m+1];
for(int i=1;i<=n;i++){
HT[i].parent=HT[i].lchild=HT[i].rchild=0;
HT[i].weight=w[i];
}
for(int i=n+1;i<=m;i++){
HT[i].parent=0;
}
for(int i=n+1;i<=m;i++){
select(HT,i-1,s1,s2);
HT[i].weight=HT[s1].weight+HT[s2].weight;
HT[s1].parent=HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
}
HC=new char*[n+1];
char *cd=new char[n];
int c=m; //m为父节点
int cdlen=0;
for(int i=1;i<=m;i++){ //作为访问标志
HT[i].weight=0;
}
while(c){ //回归根节点,根节点左右子树都访问后的父节点为0,结束循环
if(HT[c].weight==0){
HT[c].weight=1;
if(HT[c].lchild!=0){
c=HT[c].lchild;
cd[cdlen++]='0';
}
else if(HT[c].rchild==0){
cd[cdlen]='\0'; //cdlen不能加一,因为退回是退到父节点,消除的是边,'\0'不代表边
HC[c]=new char[cdlen+1]; //c为当前叶节点
strcpy(HC[c],cd);
}
}
else if(HT[c].weight==1){
HT[c].weight=2;
if(HT[c].rchild!=0){
c=HT[c].rchild;
cd[cdlen++]='1';
}
}
else {
HT[c].weight=0;
c=HT[c].parent;
--cdlen;
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
HTNode *HT;
char **HC;
HuffmanCoding(HT,HC,w,n);
for(int i=1;i<=n;i++){
printf("%s\n",HC[i]);
}
}
return 0;
}