哈夫曼树及编码讲解及例题

哈弗曼树及编码

哈弗曼树算法

第一步:

初始化n个单节点的树,并为它们表上字母中的字符。把每个字符的概率记在树的根中,用来指出树的权重(更一般地说,树的权重等于树中所有叶子的概率之和)。

第二部:

重复下面的操作,直到只剩下一颗单独的树。找到两颗权重最小的树(对于权重相同的树,可任意选择其一)。把它们作为新树中的左右子树,并把其权重之和作为新的权重记录在新树的根中。

上面的算法构造的树称为哈弗曼树,它按照刚才的描述定义了一套哈夫曼编码

例:
字符ABCD_
出现概率0.350.10.20.20.15
代码字111000001101

因此,DAD被编码为011101,而10011011011101编码以后就是BAD_AD。

构造哈弗曼编码树的一个例子图:

在这里插入图片描述

在这套编码中,每个字符的平均位长是 2 ∗ 0.35 + 3 ∗ 0.1 + 2 ∗ 0.2 + 2 ∗ 0.2 + 3 ∗ 0.15 = 2.25 2*0.35+3*0.1+2*0.2+2*0.2+3*0.15=2.25 20.35+30.1+20.2+20.2+30.15=2.25

可见,我们可以指望一个文本的哈夫曼编码要比其定长编码少占用25%的存储空间。

哈夫曼编码是一种最重要的文件压缩方法。

例图:
问题a

对于下面的数据构造一套哈弗曼编码:

字符ABCD_
出现概率0.40.10.20.150.15
答案a

在这里插入图片描述
在这里插入图片描述

问题b

用a中的编码对文本ABACABAD进行编码。

答案b

在这里插入图片描述

问题c

对于100010111001010用a中的编码进行解码

答案c

在这里插入图片描述

小结:

哈弗曼树是一颗二叉树,它使得从根出发到包含一组预定义权重的叶子之间的加权路径长度达到最小。

哈弗曼树最重要应用是哈弗曼编码。

哈弗曼编码是一种最优的自由前缀变长编码方案,它基于字符在给定文本中的出现频率,把位串赋给字符。这是通过贪心思想构造一颗二叉树来完成的,二叉树的叶子代表字母表中的字符,而树中的边则标记为0或者1。

  • 23
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
哈夫曼树是一种带权路径长度最短的,可以用于数据压缩等领域。构建哈夫曼树的过程可以通过递归实现,具体步骤如下: 1. 将所有权值存储在一个数组中,并按照从小到大的顺序排序。 2. 取出权值最小的两个节点,将它们合并成一个新节点,新节点的权值为两个节点的权值之和。 3. 将新节点插入到数组中,并按照权值从小到大的顺序排序。 4. 重复步骤2和3,直到数组中只剩下一个节点,即为哈夫曼树的根节点。 下面是C++实现哈夫曼树的代码示例: ```cpp #include <iostream> #include <queue> #include <vector> using namespace std; // 定义哈夫曼树节点结构体 struct HuffmanNode { int weight; // 权值 HuffmanNode* left; // 左子节点 HuffmanNode* right; // 右子节点 HuffmanNode(int w) : weight(w), left(nullptr), right(nullptr) {} }; // 定义比较函数,用于优先队列中节点的排序 struct cmp { bool operator()(HuffmanNode* a, HuffmanNode* b) { return a->weight > b->weight; } }; // 构建哈夫曼树 HuffmanNode* buildHuffmanTree(vector<int>& weights) { priority_queue<HuffmanNode*, vector<HuffmanNode*>, cmp> pq; for (int w : weights) { pq.push(new HuffmanNode(w)); } while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode(left->weight + right->weight); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 生成哈夫曼编码 void generateHuffmanCode(HuffmanNode* root, string code, vector<string>& codes) { if (!root) { return; } if (!root->left && !root->right) { codes.push_back(code); return; } generateHuffmanCode(root->left, code + "0", codes); generateHuffmanCode(root->right, code + "1", codes); } int main() { vector<int> weights = {5, 9, 12, 13, 16, 45}; HuffmanNode* root = buildHuffmanTree(weights); vector<string> codes; generateHuffmanCode(root, "", codes); for (int i = 0; i < weights.size(); i++) { cout << "Weight: " << weights[i] << ", Code: " << codes[i] << endl; } return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值