哈夫曼树就是前面1-n的位置存输入的n个数据,后面还要有(n-1)个空间存两个节点相加的数值,然后第一题的求带权长度就是这后面的(n-1)个空间的和,因为节点的值再这里面重复加过了。
然后是编码,从后往前找,是左子树就是0,是右子树就是1,定一个二维字符数组存下就可以了,oj上这题好像不能用数组,我用了二维指针。
下面是第二题的ac代码,第一题和第三题也是改一点点就可以了
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef struct shu
{
int mom;
int l,r,w;
} tree;
void mim(tree a[],int n,int &f1,int &f2)//找出两个最小的权,f1最小,f2其次
{
int i,m,f;
f=1;
for(i=1; i<=n; i++)
{
if(f&&a[i].mom==0)
{
f=0;
m=i;
}
else if(a[i].mom==0&&a[i].w<a[m].w)
{
m=i;
}
}
f1=m;
a[m].mom=1;//这个不能找了
f=1;
for(i=1; i<=n; i++)
{
if(f&&a[i].mom==0)
{
f=0;
m=i;
}
else if(a[i].mom==0&&a[i].w<a[m].w)
{
m=i;
}
}
f2=m;
//第三题这里加一个(如果f1>f2,swap(f1,f2)即可)
}
int main()
{
tree *a;
int n,i,f1,f2,zi,ma,t;
cin>>n;
a=new tree[2*n+1];//前n个空间你输入的数据,后面n-1个是两权和,2*n+1是因为我怕超限,嘿嘿
for(i=0; i<=2*n; i++)//初始化
{
a[i].l=0;
a[i].mom=0;
a[i].r=0;
}
for(i=1; i<=n; i++)//输入
{
cin>>a[i].w;
}
for(i=n+1; i<2*n; i++)//搞后面的空间了哦
{
mim(a,i-1,f1,f2);//两最小权相加
a[f1].mom=i;
a[f2].mom=i;
a[i].l=f1;
a[i].r=f2;
a[i].w=a[f1].w+a[f2].w;
}
//第一题这里停下,把n+1到2*n的和加起来输出就可以了
char **p,*c;
p=new char*[n+1];//相当于给了p n+1行
c=new char[n];
c[n-1]='\0';
for(i=1; i<=n; i++)
{
zi=i;
ma=a[i].mom;
t=n-1;
while(ma)
{
if(a[ma].l==zi)c[--t]='0';
else c[--t]='1';
zi=ma;
ma=a[ma].mom;
}
p[i]=new char[n-t];//相当于p的第i行有多少n-t列
strcpy(p[i],&c[t]);
}
for(i=1; i<=n; i++)
{
cout<<p[i]<<endl;
}
}