[大话数据结构] 6.12.3 赫夫曼编码

今天抽时间看了一下赫夫曼编码,感觉挺有意思。那就做个小总结。

赫夫曼树:带全路径长度WPL最小的二叉树称作赫夫曼树。具题看大话数据结构 200页 或 百度~

赫夫曼编码:按照叶子结点的权值从小到大来构造一棵赫夫曼树。 规定赫夫曼树的做分支代表0,右分支代表1,

则从根节点到叶子结点所经过的路径分支组成的序列称作赫夫曼编码。具题看大话数据结构 207页 或 百度~

我们来看下书上的例子:

假设六个字母的频率为 A 27 ,B 8,C 15,D 30,E 30,F 5,合起来正好是100%。

我们把频率低的看为结点权值小。那么我们就可以构造出一颗赫夫曼树。

可以用 结构体数组优先队列 模拟建树。

具体实现看代码吧,已经在代码后面加上详细的注释了~~

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int ans = 0, flag;
char chc[1000];
struct ak
{
    int qz;                             //权值
    char ch;                            //字母
    int arr;                            //元素所在数组下标
    bool operator < (const ak &a) const
    {
        return a.qz < qz;               //优先队列重载操作符
    }
}temp;
priority_queue<ak> pq;
struct Node
{
    int dir[2];                         //结点左孩子和右孩子
    char cc;                            //字母
}s[100000];
int gao()
{
    while(1)
    {
        int siz = pq.size();
        int father = ans++;
        s[father].cc ='$';
        int cnt = 0;
        for(int i = 0; i < 2 ; i++)
        {
            s[father].dir[i] = -1;
            if(i < siz)
            {
                temp = pq.top();
                pq.pop();
                cnt += temp.qz;
                if(temp.arr == -1)
                {
                    s[ans].cc = temp.ch;
                    s[ans].dir[0] = s[ans].dir[1] = -1;
                    s[father].dir[i] = ans++;
                }
                else
                {
                    s[father].dir[i] = temp.arr;
                }
            }
        }
        temp.qz = cnt;
        temp.ch = '$';
        temp.arr = father;
        pq.push(temp);
        if(pq.size() == 1)
        {
            return father;    //如果队列元素只剩一个了,函数调用结束。
        }
    }
}
void init()
{
    temp.arr = -1;
    temp.qz = 27, temp.ch = 'A';
    pq.push(temp);
    temp.qz = 8, temp.ch = 'B';
    pq.push(temp);
    temp.qz = 15, temp.ch = 'C';
    pq.push(temp);
    temp.qz = 15, temp.ch = 'D';
    pq.push(temp);
    temp.qz = 30, temp.ch = 'E';
    pq.push(temp);
    temp.qz = 5, temp.ch = 'F';
    pq.push(temp);
}
int dir(int x, int deep)
{
    int k = (chc[deep] == '0' ?  0 : 1);    //解码过程,如果当前数字是0那么往左走,否则往右
    if(s[x].dir[k] != -1)                   //如果有子结点,那么继续递归
    {
        return dir(s[x].dir[k], deep+1);
    }
    else                                    //如果没有子结点,递归结束
    {
        printf("%c", s[x].cc);
        return deep-1;
    }
}
int main()
{
    init();             //把大话数据结构P206页的6个字母和频率放入优先队列中
    int kk = gao();     //根据字母和频率构造赫夫曼树
    gets(chc);
    flag = 0;
    int coun = 0;
    for(; flag < strlen(chc); flag++, coun++)
    {
        flag = dir(kk, flag);
    }
    puts("");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值