1.线索二叉树

上一篇二叉树中,我们介绍了基本的二叉树的结构。每一个父节点对应两个子节点,左子节点和右子节点。其中我们会看到,很多节点的左右节点都为null,为了更高效的存储和遍历,我们考虑一种方式将这些为null的节点利用起来。这就是线索二叉树的思想,将为null的左子节点指向遍历时的前驱节点,为null的右子节点指向遍历时的后续节点。如此一来,在遍历的过程中,我们便可以直接通过左右子节点,找到叶子节点的前驱和后驱,使用一条线完整的将整刻树串起来。

2.代码实现python

在实现的过程中,我们原来的Node类中需要添加两个标志位leftType和rightType.分别表示对应的节点是普通的子节点还是前驱后驱节点。实现过程如下:首先我们构建一棵树,然后使用中序遍历这树,使用pre变量记录前一个节点。对于当前节点左子节点为null的,将其左子节点指向pre节点;如果pre的右子节点也为null,将pre的右子节点指向当前节点;

然后进行遍历,先找到最下面的左子节点,如果该节点后后驱节点,则不断遍历其后驱节点。否则的话按照普通的中序遍历寻找下一个节点(),不断遍历直到找不到任何节点。则完成整棵树的遍历。

#-*- coding:utf-8 -*-
class Node(object):def __init__(self,val):self.val = valself.left = Noneself.right=None# 左节点类型 0表示左子节点 1表示后驱self.leftType = 0# 右节点类型 0表示右子节点 1表示后驱self.rightType = 0def show(self):print("遍历--当前节点为 = {}".format(self.val),end='\t')if self.left != None and self.leftType == 0:print("左子节点为 = {}".format(self.left.val),end='\t')if self.right != None and self.rightType == 0:print("右子节点为 = {}".format(self.right.val))if self.left != None and self.leftType == 1:print("前驱节点为 = {}".format(self.left.val),end='\t')if self.right != None and self.rightType == 1:print("后驱节点为 = {}".format(self.right.val))
class ThreadTree(object):def __init__(self):self.root = Noneself.pre = None#构建一棵基本的树def build(self,values):# 将每个元素转换为node节点nodes = [None if V is None else Node(V) for V in values]# 给根节点添加左右子节点for index in range(1, len(nodes)):parent_index = (index - 1) // 2parent = nodes[parent_index]if parent is None:raise Exception('parent node missing at index{}'.format(index))if index % 2 == 0:parent.right = nodes[index]else:parent.left = nodes[index]self.root = nodes[0]return nodes[0]#在中序遍历的过程中对每个节点中left,right为null的进行复制前驱后驱节点def threadedNode(self,node):if node == None:returnself.threadedNode(node.left)# 处理当前节点的的前驱节点if node.left == None:node.left = self.prenode.leftType = 1print("当前节点={}".format(node.val))if self.pre != None:print("前驱结点为 = {}".format(self.pre.val))if self.pre != None and self.pre.right == None:# 前驱节点的右指针指向当前节点self.pre.right = nodeself.pre.rightType = 1print("当前节点={},后驱结点为 = {}".format(self.pre.val, node.val))self.pre = nodeself.threadedNode(node.right)def mid_order(self,node):while node != None:while node.leftType == 0:node = node.leftif node != None:node.show()while node.rightType == 1:node = node.rightnode.show()node = node.right
threadTree = ThreadTree()
node = threadTree.build([1,2,3,4,5,6,7,8])
threadTree.threadedNode(node)
threadTree.mid_order(node)

3.线索二叉树总结

本文介绍了线索二叉树的原理及使用python实现的过程,最核心的思想就是利用了二叉树中为null的空指针,使这些指针指向前驱和后驱节点。

4.哈夫曼树

声明:本篇博客参考自哈夫曼树及其python实现。哈夫曼树又称为最优树、最优二叉树。其最优的体现就是使得所有节点的带权路径和最小,如图所示我们看到个节点中除了值之外,还有各自的权重信息。一个节点到另外一个节点所走过的节点称为路径,比如从根节点到c,需要经过50,29,14,6;带权路径长度是这么定义的:权重乘以其对应的路径数,比如下面图中的带权路径长度WPL为:9*2+12*2+15*2+6*3+3*4+5*4 = 122。我们的目标是使得带权路径长度最小,其实就是权重越大离根节点越近,这样保证总体的带权加和值最小。

接下来我们介绍一下实现的算法:对权重列表进行排序,每次选中权重最小的两个节点作为左右子节点生成一棵树,将其权重之和作为该树的根节点。从权重列表中将这两个叶子节点删除,并且将根节点的权重加入权重列表。不断的迭代上面的过程,直到只有一个根节点为止,整棵树生成结束。

哈夫曼编码:哈夫曼树由于其带权路径长度最短,并且每个节点到根节点点的路径都是唯一的,可以用来进行编码。这是一种不等长的编码方式,在很大程度上节省了空间。

我们统计每个字在文本中出现的此处,作为其权重,构建一棵哈夫曼树,规定每棵子树的左分支路径为0,右分支路径为1。这样找到节点对应的路径,便可以沿着路径对其进行编码。比如下面的a可以编码为00,b可以编码为01;

5.python代码实现

#-*- coding:utf-8 -*-
#节点类
class Node(object):def __init__(self,name=None,value=None):self._name=nameself._value=valueself._left=Noneself._right=None#哈夫曼树类
class HuffmanTree(object):#根据Huffman树的思想:以叶子节点为基础,反向建立Huffman树def __init__(self,char_weights):#将字典中所有的值 变成node数组self.a=[Node(part[0],part[1]) for part in char_weights]  #根据输入的字符及其频数生成叶子节点while len(self.a)!=1:#每次取权重最小的两个节点 生成父节点#这两个节点分别为左右节点self.a.sort(key=lambda node:node._value,reverse=True)c=Node(value=(self.a[-1]._value+self.a[-2]._value))c._left=self.a.pop()c._right=self.a.pop()self.a.append(c)self.root=self.a[0]self.b=list(range(10))          #self.b用于保存每个叶子节点的Haffuman编码,range的值只需要不小于树的深度就行#用递归的思想生成编码def huffmanEncode(self,tree,length):node=treeif (not node):returnelif node._name:print(node._name + '的编码为:',end='\t')for i in range(length):print(self.b[i],end='\t')print ('\n')returnself.b[length]=0self.huffmanEncode(node._left,length+1)self.b[length]=1self.huffmanEncode(node._right,length+1)#生成哈夫曼编码def get_code(self):self.huffmanEncode(self.root,0)if __name__=='__main__':#输入的是字符及其频数char_weights=[('a',5),('b',4),('c',10),('d',8),('f',15),('g',2)]tree=HuffmanTree(char_weights)tree.get_code()

6.哈夫曼树总结

上面我们介绍了哈夫曼树,也称为最优二叉树。其根本的思想是使得带权路径之和最小,即权重越大的节点离根节点越近。实现算法的思路是,从权重列表中每次选择两个最小权重的节点为左右节点,其和作为根节点构成一棵树。然后从权重列表中删除这两个节点,并加入他们的和。不断的迭代直到只剩下一个根节点。然后我们介绍了哈夫曼树的实际应用之一,哈夫曼编码。规定左分支为0,右分支为1,通过节点的路径上所有分支的值生成编码。这是一种不等长,但是却能够保证节点唯一性的编码方式。大大的节省了空间。

7. 这天界,我守得,也杀得!

这天界,我守得,也杀得!我连着熬了三天两夜,终于把琉璃看完了。看完以后特别的伤心,就跟失恋了一样。真的太喜欢袁冰妍小姐姐了,那种可爱的笑容世界上再没有第二个。请允许我借用《洛神赋》中的几句诗表达我对小姐姐的仰慕:翩若惊鸿,婉若游龙。荣曜秋菊,华茂春松。髣髴兮若轻云之蔽月,飘飖兮若流风之回雪。谁能够让我见到她,你就是我这辈子最大的恩人。今天还有一个不好的消息就是,我喜欢了四年半的女神结婚了。唉!当然会很伤心了。不过这又能说明什么呢?只不过是这一段时间我需要用很多其它的东西,占满自己的思绪,避免一个人想太多留太多的泪!只不过在这一辈子短短的几十年中她不属于我而已,这么想的话就觉得人生还是过得下去的。对于别人的东西,我从来都不会再有什么期待。现在的我,只期待冰妍小姐姐的下一部电视剧。

琉璃·战神-我曾背负众生妄-燃虐向

常用数据结构之线索二叉树和哈夫曼树相关推荐

  1. 【数据结构Note5】- 树和二叉树(知识点超细大全-涵盖常见算法 排序二叉树 线索二叉树 平衡二叉树 哈夫曼树)

    文章目录 5.1 树和二叉树引入 5.1.1 树的概念 5.1.2 树的表示 5.1.3 树中基本术语 5.2 二叉树 5.2.1 概念 5.2.2 二叉树的性质 5.2.3 特殊的二叉树 5.2.4 ...

  2. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  3. 最优二叉树(哈夫曼树)知识点

    路径:在一棵树中从一个结点往下到孩子或孙子结点之间的通路 结点的路径长度:从根节点到该节点的路径上分支的数目 树的路径长度:树中每个结点的路径长度之和 结点的权:给树中的结点赋予一个某种含义的值,则该 ...

  4. 深入学习二叉树(三) 霍夫曼树

    深入学习二叉树(三) 霍夫曼树 1 前言 霍夫曼树是二叉树的一种特殊形式,又称为最优二叉树,其主要作用在于数据压缩和编码长度的优化. 2 重要概念 2.1 路径和路径长度 在一棵树中,从一个结点往下可 ...

  5. WPL、最优二叉树(哈夫曼树)

    定义:最优树,带权路径长度最短的树 基本概念: 1:路径长度:从树的一个结点到另一个结点的路径中,路径上的分支数目为路径长度 2:树的路径长度:从根结点到每个结点的路径长度之和 3:树的带权路径长度( ...

  6. java 实现最优二叉树_哈夫曼树(最优二叉树)及其Java实现

    一.定义 一些定义: 节点之间的路径长度:在树中从一个结点到另一个结点所经历的分支,构成了这两个结点间的路径上的经过的分支数称为它的路径长度 树的路径长度:从树的根节点到树中每一结点的路径长度之和.在 ...

  7. 最优二叉树(哈夫曼树)Java实现

    此篇博客讲最优二叉树也叫哈夫曼树的原理,以及构建步骤,还有哈夫曼编码原理.建议有二叉树基础朋友学习交流.对二叉树基础可以看我的另外一篇博客二叉树的构建以及遍历 文章目录 哈夫曼树引出: 哈夫曼树原理及 ...

  8. 武汉理工大学数据结构综合实验——二叉树与赫夫曼图片压缩

    文章目录 实验目的 主要仪器设备及耗材 一.实验要求 二.分析与设计 1.数据结构的设计 2.核心算法设计 生成Huffman树的算法 生成Huffman编码的算法 压缩编码的算法 3.测试用例设计 ...

  9. 【数据结构】哈夫曼编码与最优二叉树(哈夫曼树)

    一.为什么要用哈夫曼编码 在进行大容量存储.图像压缩等数据交换的时候,如果文件过大,恰好WIFI又不怎么快,你是不是会觉得十分暴躁呀?比如有这样一串数据需要传输: 上面就有100位二进制数,这还只是数 ...

最新文章

  1. Matlab怎么计算信号的能量,用Matlab求离散讯号的能量与功率怎么编程
  2. Python(2.7.6) copy - 浅拷贝与深拷贝
  3. Android代码命名规范
  4. IDEA——修改idea64.exe.vmoptions文件解决coding卡顿问题
  5. IIS无法启动——郁闷的KB939373补丁
  6. java 解析 cim e 模型 架包,基于JAVA平台的CIM模型潮流数据转换方法及装置与流程...
  7. JVM--Garbage First
  8. 我国政务大数据政策的文本分析:推进逻辑与未来进路
  9. 自己写的极简Mac番茄时间,强制黑屏休息
  10. python卡方拟合性检验_卡方分布、卡方独立性检验和拟合性检验理论及其python实现...
  11. 腾讯云播放器隐藏音频播放的按钮
  12. VESA编程——GUI离我们并不遥远
  13. 2012年8月11日
  14. TI 蓝牙4.0芯片 cc2540
  15. 关于RedisPool配置参数
  16. Gameplay框架
  17. 1399元千元真旗舰,360手机N5“能耐”在哪?
  18. 西部数据推出10TB容量监控级硬盘
  19. python字典操作 EasyDict()作用
  20. 《深度学习》学习笔记(一)

热门文章

  1. CALayer 详解 -----转自李明杰
  2. 人像摄影的美姿和构图技巧
  3. 【视频课】12小时不一样的高质量Python基础课,推荐给你学习!
  4. python游戏飞船与外星人代码
  5. linux服务器查看公网IP信息(curl)
  6. JAVA计算机毕业设计基于web的面向公众的食品安全知识系统源码+数据库+系统+lw文档
  7. 2019苹果开发者账号申请流程
  8. R语言学习笔记(excel表格读写、数据连接JION)
  9. Oracle分页查询优化
  10. day19Java-其它IO-ObjectIn(Out)putStream-(反)序列化流