哈夫曼编码

今天中秋节,同学都回家了,自己离家太远待在宿舍无聊就看看哈夫曼代码,顺手写了写,特此博客一篇,望多多指教:
对一组数进行哈夫曼树的构建:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。[2]
代码如下:
void select(HuffmanTree ht,int n,int *s1,int *s2)
{
    int min1 = INF;
    int min2 = INF;
    int i;
    *s2 = 0; 
    *s1 = 0; 
    for(i = 1; i <= n; i++)
    {
        if(ht[i].weight <= min1 && ht[i].parent == 0)//为了下一个次查找排除查找过得节点
        {
            min1 = ht[i].weight;
            *s1 = i;
        }
    }
    for(i = 1; i <= n; i++)
    {
        if(ht[i].weight <= min2 && ht[i].parent == 0 && i != *s1)
        {
            min2 = ht[i].weight;
            *s2 = i;
        }
    }
}
void InitHuffman(HuffmanTree ht,int w[],int n)
{
    int i;
    int m;
    //1-n号单元存放叶子节点,初始化
    for( i = 1; i <= n; i++)
    {
        ht[i].weight = w[i-1];
        ht[i].parent = 0;
        ht[i].LChild = 0;
        ht[i].RChild = 0;
    }
    //n+1—m号单元存放非叶子节点,初始化
    m = 2*n - 1;
    for(i = n+1; i <= m; i++)
    {
        ht[i].weight = 0;
        ht[i].parent = 0;
        ht[i].LChild = 0;
        ht[i].RChild = 0;
    }
}
void CrtHuffmanTree(HuffmanTree ht,int w[],int n)
{
    int s1,s2;
    InitHUffman(ht,w,n);
    for(i = n+1; i<= m; i++)
    {//创建哈夫曼树
        select(ht,i-1,&s1,&s2);//从0至(i-1)行中选最小的两个值
        ht[i].weight = ht[s1].weight + ht[s2].weight;
        ht[s1].parent = i;
        ht[s2].parent = i;
        ht[i].LChild = s1;
        ht[i].RChild = s2;
    }
}
这时候二叉树就构建成功了,如果想进行编码,则直接遍历每一个叶子节点就OK
得到编码
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n)
{
    char *cd;
    int i;
    int c;
    int start;
    int p;
    cd = (char*)malloc((n+1)*sizeof(char));//分配当前编码的工作空间
    cd[n-1] = '\0';//从右向左逐位存放编码,首先存放编码结束符
    for(i = 1; i <= n; i++)
    {
        start = n-1;//cd中的位置
        c = i;//第几个点
        p = ht[i].parent;
        while(p != 0)
        {
            --start;
            if(ht[p].LChild == c)
            {//左分支标0
                cd[start] = '0';
            }
            else
            {//右分支标1
                cd[start] = '1';
            }
            c = p;
            p = ht[p].parent;
        }
        //为第i个编码分配空间
        hc[i] = (char*)malloc((n-start)*sizeof(char));
        strcpy(hc[i],&cd[start]);//把编码复制到hc[i]里面
    }
}
同时祝自己中秋节快乐
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值