Python完成哈夫曼树编码过程及原理详解


Posted in Python onJuly 29, 2019

哈夫曼树原理

秉着能不写就不写的理念,关于哈夫曼树的原理及其构建,还是贴一篇博客吧。

其大概流程

Python完成哈夫曼树编码过程及原理详解

哈夫曼编码代码

# 树节点类构建
class TreeNode(object):
  def __init__(self, data):
    self.val = data[0]
    self.priority = data[1]
    self.leftChild = None
    self.rightChild = None
    self.code = ""
# 创建树节点队列函数
def creatnodeQ(codes):
  q = []
  for code in codes:
    q.append(TreeNode(code))
  return q
# 为队列添加节点元素,并保证优先度从大到小排列
def addQ(queue, nodeNew):
  if len(queue) == 0:
    return [nodeNew]
  for i in range(len(queue)):
    if queue[i].priority >= nodeNew.priority:
      return queue[:i] + [nodeNew] + queue[i:]
  return queue + [nodeNew]
# 节点队列类定义
class nodeQeuen(object):

  def __init__(self, code):
    self.que = creatnodeQ(code)
    self.size = len(self.que)

  def addNode(self,node):
    self.que = addQ(self.que, node)
    self.size += 1

  def popNode(self):
    self.size -= 1
    return self.que.pop(0)
# 各个字符在字符串中出现的次数,即计算优先度
def freChar(string):
  d ={}
  for c in string:
    if not c in d:
      d[c] = 1
    else:
      d[c] += 1
  return sorted(d.items(),key=lambda x:x[1])
# 创建哈夫曼树
def creatHuffmanTree(nodeQ):
  while nodeQ.size != 1:
    node1 = nodeQ.popNode()
    node2 = nodeQ.popNode()
    r = TreeNode([None, node1.priority+node2.priority])
    r.leftChild = node1
    r.rightChild = node2
    nodeQ.addNode(r)
  return nodeQ.popNode()

codeDic1 = {}
codeDic2 = {}
# 由哈夫曼树得到哈夫曼编码表
def HuffmanCodeDic(head, x):
  global codeDic, codeList
  if head:
    HuffmanCodeDic(head.leftChild, x+'0')
    head.code += x
    if head.val:
      codeDic2[head.code] = head.val
      codeDic1[head.val] = head.code
    HuffmanCodeDic(head.rightChild, x+'1')
# 字符串编码
def TransEncode(string):
  global codeDic1
  transcode = ""
  for c in string:
    transcode += codeDic1[c]
  return transcode
# 字符串解码
def TransDecode(StringCode):
  global codeDic2
  code = ""
  ans = ""
  for ch in StringCode:
    code += ch
    if code in codeDic2:
      ans += codeDic2[code]
      code = ""
  return ans
# 举例
string = "AAGGDCCCDDDGFBBBFFGGDDDDGGGEFFDDCCCCDDFGAAA"
t = nodeQeuen(freChar(string))
tree = creatHuffmanTree(t)
HuffmanCodeDic(tree, '')
print(codeDic1,codeDic2)
a = TransEncode(string)
print(a)
aa = TransDecode(a)
print(aa)
print(string == aa)

接下来就是一段一段分析代码

1.树结点类的构建:

共有5个属性:结点的值,结点的优先度,结点的左子结点,结点的右子结点,结点值的编码(这个没有什么好说的,这些属性都是被需要的)

2.创建树结点队列函数:

对于所有的字母结点,我们将其组成一个队列,这里使用list列表来完成队列的功能。将所有树节点够放进列表中,当然传进来的是按优先度从小到大已排序的元素列表

3.为队列添加节点元素,并保证优先度从大到小排列:

当有新生成的结点时,需将其插入列表,并放在合适位置,使队列依然时按优先度从小打到排列的。

4.结点队列类定义:

创建类初始化时需要传进去的是一个列表,列表中的每个元素是由字母与优先度组成的元组。元组第一个元素是字母,第二个元素是优先度(即在文本中出现的次数)

类初始化化时,调用“创建树结点队列函数”,队列中的每个元素都是一个树结点。

类中还包含一个队列规模属性以及另外两个操作函数:添加结点函数和弹出结点函数。

添加结点函数直接调用之前定义的函数即可,输入的参数为队列和新结点,并且队列规模加一

弹出第一个元素则直接调用列表的pop(0)函数,同时队列规模减一

5.计算文本中个字母的优先度,即出现的次数:

定义一个字典,遍历文本中的每一个字母,若字母不在字典里说明是第一次出现,则定义该字母为键,另键值为1,若在字典里有,则只需将相应的键值加一。 遍历后就得到了每个字母出现的次数。

6.由哈夫曼树得到编码表:

这里定义了两个全局字典,用于存放字母编码,一个字典用于编码,另一个字典用于解码,这样程序操作起来比较方便。

这里主要就是遍历,运用的是二叉树的中序遍历。如果明白中序遍历的化,就能看懂这里的代码,每递归到深一层的时候,就在后面多加一个‘0'(左子树)或‘1'(右子树)。

中序遍历我在上一篇博客中讲的还算可以吧,不懂的可以参考一下,否则就可以略过这一段。

这一段是哈夫曼编码的关键,也是难点,希望能够好好理解一下,也是对递归的一个理解。这一点没问题的话,我觉得哈夫曼树真的挺简单的!!!

7.字符串编码,字符串解码:

这两段我就不详细说了,应为已经有编码与解码的字典了,所以对应每一个字母直接在字典里找就好了,而且字典的寻找速度还是相当快的。

差不多了,例子就不举了,确实哈夫曼树比之前的什么八皇后问题还有KMP问题简单多了。

最后向Huffman大神致敬,祝各位学有所成。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 Python
Python的Django框架安装全攻略
Jul 15 Python
Python 爬虫爬取指定博客的所有文章
Feb 17 Python
详解python的几种标准输出重定向方式
Aug 15 Python
python实现获取Ip归属地等信息
Aug 27 Python
Jupyter notebook远程访问服务器的方法
May 24 Python
深度学习入门之Pytorch 数据增强的实现
Feb 26 Python
Python callable内置函数原理解析
Mar 05 Python
基于Python计算圆周率pi代码实例
Mar 25 Python
Python同时迭代多个序列的方法
Jul 28 Python
Node.js 和 Python之间该选择哪个?
Aug 05 Python
python实现b站直播自动发送弹幕功能
Feb 20 Python
Python秒算24点实现及原理详解
Jul 29 #Python
django之状态保持-使用redis存储session的例子
Jul 28 #Python
django 通过URL访问上传的文件方法
Jul 28 #Python
django使用admin站点上传图片的实例
Jul 28 #Python
Python中变量的输入输出实例代码详解
Jul 28 #Python
对django中foreignkey的简单使用详解
Jul 28 #Python
解决django 新增加用户信息出现错误的问题
Jul 28 #Python
You might like
ThinkPHP控制器里javascript代码不能执行的解决方法
2014/11/22 PHP
Zend Framework教程之视图组件Zend_View用法详解
2016/03/05 PHP
CI操作cookie的方法分析(基于helper类库)
2016/03/28 PHP
PHP聚合式迭代器接口IteratorAggregate用法分析
2017/12/28 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
2017/12/25 PHP
PHP二维索引数组的遍历实例分析【2种方式】
2019/06/24 PHP
jQuery EasyUI API 中文文档 - ComboTree组合树
2011/10/11 Javascript
jQuery 删除或是清空某个HTML元素示例
2014/08/04 Javascript
jquery+ajax实现注册实时验证实例详解
2015/12/08 Javascript
关于获取DIV内部内容报错的原因分析及解决办法
2016/01/29 Javascript
用JavaScript实现让浏览器停止载入页面的方法
2017/01/19 Javascript
微信小程序利用canvas 绘制幸运大转盘功能
2018/07/06 Javascript
jQuery实现购物车的总价计算和总价传值功能
2018/11/28 jQuery
vue+egg+jwt实现登录验证的示例代码
2019/05/18 Javascript
layui动态绑定事件的方法
2019/09/20 Javascript
JS如何把字符串转换成json
2020/02/21 Javascript
[00:31]2016完美“圣”典风云人物:国士无双宣传片
2016/12/04 DOTA
[53:10]完美世界DOTA2联赛决赛日 FTD vs GXR 第二场 11.08
2020/11/11 DOTA
python进阶教程之循环相关函数range、enumerate、zip
2014/08/30 Python
python实现猜单词小游戏
2020/05/22 Python
Python pygorithm模块用法示例【常见算法测试】
2018/08/16 Python
使用selenium模拟登录解决滑块验证问题的实现
2019/05/10 Python
python实现简单聊天室功能 可以私聊
2019/07/12 Python
python装饰器原理与用法深入详解
2019/12/19 Python
python Matplotlib数据可视化(1):简单入门
2020/09/30 Python
python反爬虫方法的优缺点分析
2020/11/25 Python
Probikekit日本:自行车套件,跑步和铁人三项装备
2017/04/03 全球购物
加拿大城市本地限时优惠:Buytopia.ca
2018/09/19 全球购物
美国椅子和沙发制造商:La-Z-Boy
2020/10/25 全球购物
介绍一下SQL注入攻击的种类和防范手段
2012/02/18 面试题
乡村教师党员四风问题对照检查材料思想汇报
2014/10/08 职场文书
看上去很美观后感
2015/06/10 职场文书
宣传部部长竞选稿
2015/11/21 职场文书
2016最新离婚协议书范本及程序
2016/03/18 职场文书
如何使用vue3打造一个物料库
2021/05/08 Vue.js
浅谈哪个Python库才最适合做数据可视化
2021/06/28 Python