Huffman树

从树中一个结点到另外一个结点路径上的分支数目,称作路径长度。

结点的带权路径长度为从该结点到根结点之间的路径长度与结点上权的乘积。

Huffman树,又称最优树,是带权路径长度最短的树。树的带权路径长度是树中所有叶子结点的带权路径长度之和。

Huffman树的构造方法是不断地选取权值最小的两棵树作为左右子树构造一棵新的二叉树,其权值为两棵子树的权值之和,直到只有一棵树为止。

Huffman编码是Huffman树的主要应用,Huffman编码是根据字符使用频率确定字符编码。

一棵含有n个叶子结点的Huffman树共有2n-1个结点,存储在一维数组中。 求编码时,需要从叶子结点向上走到根结点,并且该叶子结点若为双亲的左子树,则编码为0,右子树编码为1。

/*在前n个结点中选择两个权值最小的并且parent为0(树根)的结点*/
void select(HTNode huftree[],int n,int &s1,int &s2)
{
    int i,min1,min2;
    int temp;
    min1 = INT_MAX;
    min2 = INT_MAX;
    for(i=1; i<=n; i++)
        if(huftree[i].parent == 0 && huftree[i].weight<min1)
            min1 = huftree[i].weight,s1 = i;
    for(i=1; i<=n; i++)
        if(huftree[i].parent == 0 && huftree[i].weight<min2 && i!=s1)
            min2 = huftree[i].weight,s2 = i;
    //必须比较:保证s1<s2,因为若weight的值相同的话,s1取后者,s2取前者,使s1>s2
    if(s1>s2)
    {
        temp = s1;
        s1 = s2;
        s2 = temp;
    }
}

void HuffmanCoding(HTNode HT[],HuffmanCode &HC,int w[],int n)
{
    char cd[n];
    int start;
    int i;
    int c,f;
    int s1,s2;
    if(n <= 1) return ;
    int m = 2 * n - 1;
    for(i=1; i<=n; i++)
    {
        HT[i].weight = w[i-1];
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }
    for(i=n+1; i<=m; i++)
    {
        HT[i].weight = 0;
        HT[i].parent = 0;
        HT[i].lchild = 0;
        HT[i].rchild = 0;
    }
    /*构造Huffman树*/
    for(i=n+1; i<=m; i++)
    {
        select(HT,i-1,s1,s2);
        HT[s1].parent = i;
        HT[s2].parent = i;
        HT[i].lchild = s1;
        HT[i].rchild = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight;
    }
    /*求解Huffman编码*/
    HC = (HuffmanCode)malloc((n+1)*sizeof(char *));
    cd[n-1] = '\0';
    for(i=1; i<=n; i++)
    {
        start = n-1;
        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));
        strcpy(HC[i],&cd[start]);
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值