前引
这应该是倒数第二篇关于算法的了
现在想想算法这本书就快要走到尽头了 我也是不知道之前我怎么慢慢坚持把整本书大部分的内容都记录了下来 并写了绝大部分的代码实现的
关于哈夫曼树 我的记忆特别特别清楚
就是做了浙大数据结构中的一道题 叫做Huffman Codes
相关我的习题博客链接 和关于哈夫曼树习题的链接我放在最底下面
如果有想要完全挑战一下自己的可以尝试做一下 浙大的哈夫曼树的题
我反正记得我做了可能有个整两天左右哈哈哈哈哈 就是完全从头开始做
真的做了超级久超级久 到现在竟然哈夫曼树大概是什么都忘记了
就着现在对算法进行个总结 我也顺带回忆回忆大概的内容吧
浙大数据结构讲解哈夫曼树视频链接
我的理解
哈夫曼树存在的意义
比如我们记录数据用的是树来记录
那我们就假设把数据随意放位置
那当我们在树中寻找那些数据时 那是不是会出现有些数据我们查找频率会很多 有些又相对会很少
比如一些常用的数据 我们查找频率相对就高的多
ok 那这个时候我们来计算一下每次调用查找的成本了
假设 我们把我们最经常调用的数据 放到了树的最底下 也就是叶节点位置
那当我们查找的时候 是不是每次都要把整个树的高度的数据遍历一次
我们才能走到树的最底下
相反 如果我们把数据放到最顶上面 很显然 每次我们一调用查找就ok了
那么此时哈夫曼树就为此诞生了
我们针对不同权值的节点 放到不同的位置就ok了
那哈夫曼树干嘛呢
就是使我们WPL最小 WPL是树的所有叶结点的带权路径长度之和
用通俗点的话 意义来讲 就是可以使我们的数据总调用查找的成本最小
我是这个样子理解的
哈夫曼编码存在的意义
我是这样理解的(水平有限 仅用自己的话来表达)
就是比如 我们用固定的二进制编码8位来记录字符
比如我们记录一共10000个字符 那么一共就需要8w位
那么如果记录1亿个字符 那么一共就需要8亿位
很显然 8位很多时候是不够的
但是对于每一个字符来说 有些字符很小 那么剩下的位对于他来说就是铁浪费
但是对于有些字符来说 是比较合适的
那么我们就可以计算一下空间利用率
如果字符中存在非常多的ascii或unicode很小的字符
而只出现很少很少的"大"字符的情况
那么空间浪费是不是就特别的吓人了
所以针对这种情况 一种编码形式就出现了
如何构建哈夫曼树
我们可以通过 最小堆来实现
具体的实现步骤大家可以看看视频链接了解一下
这里我就简单概括一下
哈夫曼树就是把 序列节点中最小的两个权值点合并变成一棵树
父节点的值就是两个子节点的权值之和
我们又把父节点的值放到序列中 继续进行合并
直到合并到只有一个权值
那么我们如何在序列中挑选两个权值最小的节点呢
用C++的STL库 我们可以使用priority_queue优先队列
那么c语言的话 我们只能自己造一个最小堆了
最小堆的基本操作 什么插入 删除 如果不是很清楚的话
也可以看一下我的博客 专门写了最小堆的操作的
好像是最大堆 但是思想是一样的
算法C++ 优先队列 堆排序大顶堆代码实现(第二章)
哈夫曼编码构建
既然我们把树都建立好了
编码怎么编呢 下面一张图就表示了
具体就是用 0-1编码
如果子节点在右边的话 就是1 子节点在左边的就是0
这样既能保证 不出现二重性 一个字符只有一串编码
而且又能使 字符的节省空间率大大增加
相比较 我们一个字符固定字符数
节省空间率那肯定大大增加
哈夫曼树习题+习题博客链接
需要注册pta账号 注册十分简单
7-9 Huffman Codes (30 分)