数据结构-哈夫曼树(python实现)
好,前面我们介绍了一般二叉树、完全二叉树、满二叉树,这篇文章呢,我们要介绍的是哈夫曼树。
哈夫曼树也叫最优二叉树,与哈夫曼树相关的概念还有哈夫曼编码,这两者其实是相同的。哈夫曼编码是哈夫曼在1952年提出的。现在哈夫曼编码多应用在文本压缩方面。接下来,我们就来介绍哈夫曼树到底是个什么东西?哈夫曼编码又是什么,以及它如何应用于文本压缩。
哈夫曼树(Huffman Tree)
给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
首先,我们有这样一些数据:
sourceData = [('a', 8), ('b', 5), ('c', 3), ('d', 3), ('e', 8), ('f', 6), ('g', 2), ('h', 5), ('i', 9), ('j', 5), ('k', 7), ('l', 5), ('m', 10), ('n', 9)]
每一个数据项是一个元组,元组的第一项是数据内容,第二项是该数据的权重。也就是说,用于构建哈夫曼树的数据是带权重的。假设这些数据里面的字母a-n的权重是根据这些字母在y一个文本出出现的概率计算得出的,字母出现的概率越高,则该字母的权重越大。例如字母 a 的权重为 8 .
好,拿到数据我们就可以来构建哈夫曼树了。
- 首先,找出所有元素中权重最小的两个元素,即g(2)和c(3),
- 以g和c为子节点构建二叉树,则构建的二叉树的父节点的权重为 2+3 = 5.
- 从除g和c以外剩下的元素和新构建的权重为5的节点中选出权重最小的两个节点,
- 进行第 2 步操作。
以此类推,直至最后合成一个二叉树就是哈夫曼树。
我们用图例来表示一下:
好,这里我们的哈夫曼树就构建好了,节点中字母后面的数字表示该字母的权重,就是前面给定的数据。在这里我要强调的是,同样的数据创建的哈夫曼树并不是唯一的,所以只要按照规则一步一步没有出错,你的哈夫曼树就是正确的。
我们现在将访问左节点定义为0,访问右节点定义为1.则我们现在访问字母a,则它的编码为0110,访问字母n的编码为111,这个编码就是哈夫曼编码。
通过比对不同字母的哈夫曼编码,你发现了什么?
权重越大的字母对应的哈夫曼编码越短,权重越小的字母对应的哈夫曼编码则越长。也就是说文本中出现概率大的字母编码短,出现概率小的字母编码长。通过这种编码方式来表示文本中的字母,那所得整个文本的编码长度也会缩短。
这就是哈夫曼树也就是哈夫曼编码在文本压缩中的应用。
下面我们用代码来实现:
定义一个二叉树类:
class BinaryTree:
def __init__(self, data, weight):
self.data = data
self.weight = weight
self.left = None
self.right = None
获取节点列表中权重最小的两个节点:
# 定义获取列表中权重最大的两个节点的方法:
def min2(li):
result = [BinaryTree(None, float('inf')), BinaryTree(None, float('inf'))]
li2 = []
for i in range(len(li)):
if li[i].weight < result[0].weight:
if result[1].weight != float('inf'):
li2.append(result[1])
result[0], result[1] = li[i], result[0]
elif li[i].weight < result[1].weight:
if result[1].weight != float('inf'):
li2.append(result[1])
result[1] = li[i]
else:
li2.append(li[i])
return result, li2
定义生成哈夫曼树的方法:
def makeHuffman(source):
m2, data = min2(source)
print(m2[0].data, m2[1].data)
left = m2[0]
right = m2[1]
sumLR = left.weight + right.weight
father = BinaryTree(None, sumLR)
father.left = left
father.right = right
if data == []:
return father
data.append(father)
return makeHuffman(data)
定义广度优先遍历方法:
# 递归方式实现广度优先遍历
def breadthFirst(gen, index=0, nextGen=[], result=[]):
if type(gen) == BinaryTree:
gen = [gen]
result.append((gen[index].data, gen[index].weight))
if gen[index].left != None:
nextGen.append(gen[index].left)
if gen[index].right != None:
nextGen.append(gen[index].right)
if index == len(gen)-1:
if nextGen == []:
return
else:
gen = nextGen
nextGen = []
index = 0
else:
index += 1
breadthFirst(gen, index, nextGen,result)
return result
输入数据:
# 某篇文章中部分字母根据出现的概率规定权重
sourceData = [('a', 8), ('b', 5), ('c', 3), ('d', 3), ('e', 8), ('f', 6), ('g', 2), ('h', 5), ('i', 9), ('j', 5), ('k', 7), ('l', 5), ('m', 10), ('n', 9)]
sourceData = [BinaryTree(x[0], x[1]) for x in sourceData]
创建哈夫曼树并进行广度优先遍历:
huffman = makeHuffman(sourceData)
print(breadthFirst(huffman))
OK ,我们的哈夫曼树就介绍到这里了,你还有什么不懂的问题记得留言给我哦。
数据结构-哈夫曼树(python实现)的更多相关文章
- C#数据结构-赫夫曼树
什么是赫夫曼树? 赫夫曼树(Huffman Tree)是指给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小.哈夫曼树(也称为最优二叉树)是带权路径长度最短的树,权值较大的结点 ...
- Java数据结构和算法(四)赫夫曼树
Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...
- 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- 【数据结构】赫夫曼树的实现和模拟压缩(C++)
赫夫曼(Huffman)树,由发明它的人物命名,又称最优树,是一类带权路径最短的二叉树,主要用于数据压缩传输. 赫夫曼树的构造过程相对比较简单,要理解赫夫曼数,要先了解赫夫曼编码. 对一组出现频率不同 ...
- Android版数据结构与算法(七):赫夫曼树
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 近期忙着新版本的开发,此外正在回顾C语言,大部分时间没放在数据结构与算法的整理上,所以更新有点慢了,不过既然写了就肯定尽力将这部分完全整理好分享出 ...
- 6-9-哈夫曼树(HuffmanTree)-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版
课本源码部分 第6章 树和二叉树 - 哈夫曼树(HuffmanTree) ——<数据结构>-严蔚敏.吴伟民版 源码使用说明 链接☛☛☛ <数据结构-C语言版> ...
- 20172332 2017-2018-2 《程序设计与数据结构》Java哈夫曼编码实验--哈夫曼树的建立,编码与解码
20172332 2017-2018-2 <程序设计与数据结构>Java哈夫曼编码实验--哈夫曼树的建立,编码与解码 哈夫曼树 1.路径和路径长度 在一棵树中,从一个结点往下可以达到的孩子 ...
- hdu 2527:Safe Or Unsafe(数据结构,哈夫曼树,求WPL)
Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 数据结构之C语言实现哈夫曼树
1.基本概念 a.路径和路径长度 若在一棵树中存在着一个结点序列 k1,k2,……,kj, 使得 ki是ki+1 的双亲(1<=i<j),则称此结点序列是从 k1 到 kj 的路径. 从 ...
随机推荐
- Qt通过HTTP POST上传文件(python做服务端,附下载)
本文使用Qt Creator用HTTP POST的方法上传文件,并给出一个上传文件的例程. 本文主要客户端,所以对于服务器端程序编写的描述会比较简略 服务器使用Django编写,django服务器接收 ...
- C++大小写转换和性能(C语言,C++,API,STL一共4种方法)
大小写转换和性能 前言 本文主要讨论最基本的一些大小写转换函数和API,不讨论一些常见的字符串程序库里面的大小写转换接口,另外本文的落脚点是这些转换函数的性能和日常开发中遇到的一些问题. 不考虑范围 ...
- 由TreeView 如何触发OnSelectedNodeChanged事件想到的与做到的
前提是每层的结点上设置了NavigateUrl OnSelectedNodeChanged事件好像失去了作用. 另外TreeView是没有AutoPostBack的!!!! 那么要如何触发OnSele ...
- Spring之基于注解的注入
对于DI使用注解,将不再需要在Spring配置文件中声明Bean实例.Spring中使用注解,需要在原有Spring运行环境基础上再做一些改变,完成以下三个步骤. (1)导入AOP的Jar包.因为注解 ...
- Vue.js 是如何实现 MVVM 的?
目录 框架到底为我们做了什么? 如何理解 MVVM ? 如何实现 MVVM - 以 Vue.js 为例 Vue 如何实现响应式 Vue 如何解析模板 Vue.js 运行机制 手写一个 Vue.js 框 ...
- SSM(一)Mybatis基础
1.持久化与ORM 持久化是数据在内存与硬盘间相互转化的过程 ORM即对象关系映射 程序员使用面向对象的思维方式处理数据,每个对象都是一个pojo.但是保存数据的时候,却以关系型数据库的方式存储.所以 ...
- python算法与数据结构-二叉树的代码实现(46)
一.二叉树回忆 上一篇我们对数据结构中常用的树做了介绍,本篇博客主要以二叉树为例,讲解一下树的数据结构和代码实现.回顾二叉树:二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left ...
- tar命令中的 -C 作用
我用这个命令:tar zcvf chao.tar.gz /chao/* 打包文件的时候,在压缩包里把 /chao/这个路径也打包进去了. [root@yunwei-test chao]# ls / ...
- CSS3过渡与动画
一.CSS3 过渡 transition-property 规定过渡效果的 CSS 属性名 -webkit-transition-property: none / all / property; -m ...
- Cisco packet tracer下dhcp的配置的vlan的应用
话不多说,先上拓扑图. pc0和pc1分别接在三层交换机的F0/1.F0/2接口,ser接在F0/24接口,用ser用作dhcp的服务器. 0x01:配置server0 先配置server的IP地址. ...