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通过zlib实现压缩与解压字符串的方法
Nov 19 Python
对python中array.sum(axis=?)的用法介绍
Jun 28 Python
实例讲解python中的协程
Oct 08 Python
Python自定义一个类实现字典dict功能的方法
Jan 19 Python
django 信号调度机制详解
Jul 19 Python
Python BeautifulSoup [解决方法] TypeError: list indices must be integers or slices, not str
Aug 07 Python
python爬虫 正则表达式解析
Sep 28 Python
浅析PEP572: 海象运算符
Oct 15 Python
Python之Numpy的超实用基础详细教程
Oct 23 Python
python 用 xlwings 库 生成图表的操作方法
Dec 22 Python
Python 求向量的余弦值操作
Mar 04 Python
Python+OpenCV实现图片中的圆形检测
Apr 07 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
PHP中使用smarty生成静态文件的例子
2014/04/24 PHP
Yii Framework框架获取分类下面的所有子类方法
2014/06/20 PHP
PHP遍历XML文档所有节点的方法
2015/03/12 PHP
PHP中如何使用session实现保存用户登录信息
2015/10/20 PHP
php使用ffmpeg向视频中添加文字字幕的实现方法
2016/05/23 PHP
Laravel-admin之修改操作日志的方法
2019/09/30 PHP
常见的5个PHP编码小陋习以及优化实例讲解
2021/02/27 PHP
用正则获取指定路径文件的名称
2007/02/27 Javascript
Mootools 1.2教程 选项卡效果(Tabs)
2009/09/15 Javascript
javascript每日必学之基础入门
2016/02/16 Javascript
js仿3366小游戏选字游戏
2016/04/14 Javascript
jQuery插件EasyUI获取当前Tab中iframe窗体对象的方法
2016/08/05 Javascript
Angular2 PrimeNG分页模块学习
2017/01/14 Javascript
nodejs中解决异步嵌套循环和循环嵌套异步的问题
2017/07/12 NodeJs
js模拟百度模糊搜索的实例
2017/08/04 Javascript
vue服务端渲染的实例代码
2017/08/28 Javascript
微信小程序富文本渲染引擎的详解
2017/09/30 Javascript
bootstrap下拉框动态赋值方法
2018/08/10 Javascript
vue中使用codemirror的实例详解
2018/11/01 Javascript
[00:37]2016完美“圣”典风云人物:rOtk宣传片
2016/12/09 DOTA
[02:21]2018完美盛典章节片——初心
2018/12/17 DOTA
pymongo实现控制mongodb中数字字段做加法的方法
2015/03/26 Python
python xml解析实例详解
2016/11/14 Python
pygame 精灵的行走及二段跳的实现方法(必看篇)
2017/07/10 Python
python下载文件记录黑名单的实现代码
2017/10/24 Python
redis之django-redis的简单缓存使用
2018/06/07 Python
Flask模板引擎之Jinja2语法介绍
2019/06/26 Python
python+selenium 点击单选框-radio的实现方法
2019/09/03 Python
pytorch学习教程之自定义数据集
2020/11/10 Python
美国亚洲时尚和美容产品的一站式网上商店:Stylevana
2019/09/05 全球购物
俄罗斯儿童和青少年服装、鞋子及配件的在线商店:Orby
2020/02/20 全球购物
2014年向国旗敬礼活动方案
2014/09/27 职场文书
测量员岗位职责
2015/02/14 职场文书
运动会表扬稿范文
2015/05/05 职场文书
MATLAB 如何求取离散点的曲率最大值
2021/04/16 Python
SQL Server使用PIVOT与unPIVOT实现行列转换
2022/05/25 SQL Server