hnust 2184 huffman编码(三题都可)

          哈夫曼树就是前面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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值