10.6 哈夫曼(Huffman)树(1) 建立哈夫曼树(2) 哈夫曼编码

目录

10.6 哈夫曼(Huffman)树

(1) 建立哈夫曼树

(2) 哈夫曼编码


10.6 哈夫曼(Huffman)树

(1) 建立哈夫曼树

1. 哈夫曼树(最优二叉树):带权路径长度最小的二叉树。
 树的路径长度:一棵树的每一个叶结点到根结点的路径长度的和。
 带权二叉树:给树的叶结点赋上某个实数值(称叶结点的权)。
 带权路径长度:各叶结点的路径长度与其权值的积的总和。
2. 如何构建哈夫树:贪心策略——权越大离根越近。
① 首先,创建 n 个初始的 Huffman 树,每棵树只包含单一的叶结点,叶结点记录对应字母。
② 接着拿走权最小但没有被处理的两棵树,再把它们标记为 Huffman 树的叶结点。
③ 把这两个叶结点标记为一个分支结点的两个子结点,而这个结点的权即为两个叶结点的权之和。
④ 重复上述步骤,直到序列中只剩下一个元素。

int n;
struct node
{
int w;
int parent, leftchild, rightchild;
} h[M];
node * buildtree(int *weight) // weight[i]表示结点i的权值。返回值是Huffman的树根。
{
int p1, p2;
int min1, min2;
memset(h,-1,sizeof(h));
for (int i=0; i<n; i++) h[i].w=weight[i];
int m=2*n-1;
for (int i=n; i<m; i++)
{
min1=min2=INF;
for (int j=0; j<i; j++)
if (h[j].parent==-1)
{
if (h[j].w < min1)
min2=min1, min1=h[j].w, p2=p1, p1=j;
else if (h[j].w < min2)
min2=h[j].w, p2=j;
}
h[p1].parent=i;
h[p2].parent=i;
h[i].leftchild=p1;
h[i].rightchild=p2;
h[i].w=h[p1].w+h[p2].w;
}
return &h[2*n-2];
}

(2) 哈夫曼编码

哈夫曼码:哈夫曼树的非叶结点到左右孩子的路径分别用 0,1 表示,从根到叶的路径序列即为哈夫曼码。
它的特点如下:
① 代码长度取决于对应字母的相对使用频率(或者“权”),因此它是一种变长编码。
② 任何一字符的编码不是更长编码的前缀部分(否则在解码时会发生混淆)。
举一个例子:假如有几个字母,代码如下

 

 那么按照上面规则,“cell”对应的代码就是“11100110110”,“1011001110111101”对应的单
词就是“duck”。
解码过程如下:从左到右逐位判别代码串,直到确定一个字母。具体的字母需要通过 Huffman 树确定。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值