python数据结构-树
树树是数据元素之间具有层次关系的非线性结构,由n个节点构成的有限集合,节点数为0的树叫空树树:有且仅有一个被称为根的节点其余节点可分为m个互不相交的有限集合,每个集合又构成一棵树,叫做根节点的子树树中的元素具有一对多的逻辑关系除根节点以外,每个数据元素可以有多个后继但有且仅有一个前驱树是递归定义的节点的路径:根节点到该节点所经过节点的顺序排序路径的长度:路径的长度指的是路径中包含的分支数节点的度:
树
树是数据元素之间具有层次关系的非线性结构,由n个节点构成的有限集合,节点数为0的树叫空树
树:
- 有且仅有一个被称为根的节点
- 其余节点可分为m个互不相交的有限集合,每个集合又构成一棵树,叫做根节点的子树
树中的元素具有一对多的逻辑关系
除根节点以外,每个数据元素可以有多个后继但有且仅有一个前驱
树是递归定义的
节点的路径:根节点到该节点所经过节点的顺序排序
路径的长度:路径的长度指的是路径中包含的分支数
节点的度:节点的度指的是节点拥有的子树的数目
树的度:树的度指的是树中所有节点的度的最大值
叶节点:树中度为0的节点,也叫终端节点
分支节点:分支节点不是树中度不为0的节点,也叫非终端节点
节点层次:根节点的层次为0,其他节点的层次是父节点的层次+1
森林:由多个互不相交的树构成的集合
给森林加上一个根节点就变成了一棵树
同样,将树的根节点删除就变成了森林
二叉树
二叉树是特殊的有序树,它是由n个节点构成的有限集合
当n=0时称为空二叉树
二叉树的每个节点最多只有两棵子树,子树也为二叉树,互不相交且有左右之分,分别为左二叉树和右二叉树
二叉树也是递归定义的,在树中定义的度,层次等术语同样也适用于二叉树
二叉树的性质
- 二叉树中第i层的节点数最多为2i
- 深度为h的二叉树最多有2^h-1个节点
树的深度是指树中所有节点的层次数的最大值+1
树的层次从0开始算
- 二叉树的叶节点数为n,度为2的节点数为m,n = m + 1
树的度:树中所有节点的度的最大值
节点的度:指的是节点拥有子树的数目
- 具有n个节点的完全二叉树,其深度为
树的深度指树种所有节点的层次数的最大值加1 - 具有n个节点的完全二叉树,从根节点开始自上而下,自左而右的对节点从0开始编号,对于任意一个编号为i的节点:
- 若i = 0,节点为根节点,没有父节点,若i>0,则父节点的编号为(i-1)/2
- 若2I+1 >= n,该节点无左孩子,否则左孩子节点的编号为2i + 1
- 若2i+2>= n,该节点无右孩子,否则有孩子节点的额编号为2i+2
满二叉树
满二叉树是特殊的二叉树,要求除叶节点以外的其他节点都具有两颗子树,并且所有的叶节点都在同一层上
完全二叉树
若完全二叉树具有n个节点,要求n个节点与满二叉树的前n个节点具有完全相同的逻辑结构
二叉搜索树
左子树不空,左子树所有节点值均小于或等于该节点的值
右子树不空,右子树所有节点的值均大于或等于该节点的值
左右子树也叫二叉查找树
二叉排序树:中序遍历会得到一个从小到大的序列
字典树tree树/前缀树
有序:统计,排序,存储字符串
关键字保存在树中,由节点在树中的位置决定
从第一次到某个孩子节点,代表了存储的字符串
一般情况下,不是所有的节点都有存储字符串
只有叶子节点和部分特殊的节点进行了标记
利用公共前缀减少存储与查询时间
减少比较,提高效率
二叉堆
最大堆:各个节点的值大于等于子节点
最小堆:各个节点的值小于等于子节点
最大堆中最大元素在根
最小堆中最小元素在根
顺序存储二叉树
二叉树的顺序存储结构是指将二叉树的各个节点存放在一组地址连续的存储单元中,所有节点按节点序号进行顺序存储
二叉树为非线性结构,必须先将二叉树的节点排列成线性序列在进行存储,实际上是先对二叉树进行依次层次遍历
存储非完全二叉树需要添加虚拟节点
链式存储二叉树
二叉树的链式存储结构是将二叉树的各个节点随机存放在存储空间中,二叉树的各节点间的逻辑关系由指针确定
二叉链式存储结构
二叉树的每个节点设置两个指针域和一个数据域
采用二叉链表存储二叉树,每个节点只存储了到其他孩子节点的单向关系,没有存储到其父节点的关系,因此要获得父节点将花费较多的时间,需要从根节点开始在二叉树中进行查找,所花费的时间是遍历部分二叉树的时间,与查找节点所处的位置有关
存储结构空间利用率高
二叉链式存储结构更常用
class BiTreeNode:
def __init__(self,data = None,lchild = None,rchild = None):
self.data = data # 数据域的值
self.lchild = lchild # 左孩子的指针
self.rchild = rchild # 右孩子的指针
class BiTree:
def __init__(self,root = None):
self.root = root # 二叉树的根节点
# 二叉树的遍历:递归算法简洁,易于实现,但是在时间上开销较大,运行效率较低
# 二叉树的遍历指沿着某条搜索路径访问二叉树的节点,每个节点被访问的次数有且只有依次
# 层次遍历:自上而下,自左而右
# 先序遍历:先访问根节点,在遍历左子树,在遍历右子树
def preOrder(self):
if self.root is not None:
print(self.root.data)
self.preOrder(self.root.lchild)
self.preOrder(self.root.rchild)
# 非递归线性遍历:采用临时遍历保存中间结构,用循环结构代替递归过程,利用栈保存中间结果
# 利用栈结构通过回溯访问二叉树的每个节点
def preOrder2(self):
""""""
p = self.root
s = [] # python中列表就是栈
s.push(p)
while s:
p = s.pop()
print(p.data)
while p is not None:
if p.lchild is not None:
print(p.lchild.data)
if p.rchild is not None:
s.append(p.rchild)
p = p.lchild
# 中序遍历:先遍历左子树,在访问根节点,在遍历右子树
def inOrder(self):
if self.root is not None:
self.preOrder(self.root.lchild)
print(self.root.data)
self.preOrder(self.root.rchild)
# 后续遍历:先遍历左子树,在遍历右子树,最后访问根节点
def postOrder(self):
if self.root is not None:
self.preOrder(self.root.lchild)
self.preOrder(self.root.rchild)
print(self.root.data)
二叉树遍历算法的应用
- 二叉树上的查找算法
二叉树上的查找是在二叉树中查找值为x的节点,若找到返回该节点,否则返回空值 - 统计二叉树的节点个数的算法
二叉树的节点个数等于根节点加上左右子树节点的个数 - 二叉树的深度
二叉树的深度是所有节点的层次数的最大值+1,也就是左右子树的深度的最大值+1
先序遍历:ABCDEGFIG
后续遍历的时候根总在最后,所以可以一次性确定三个根
然后根据中序遍历可以确定根的左右子树
三叉链式存储结构
二叉树的每个节点设置3个指针域和一个数据域
数据域中存放节点的值,指针域中存放左右孩子节点和父节点的存储地址
便于查找孩子节点,也便于查找父节点
哈夫曼树及哈夫曼编码
哈夫曼编码是数据压缩技术中的无损压缩技术
哈夫曼树就是每次把最小得两个放到一颗二叉树里面,然后将得到的值放入原数据继续求最终遍历完所有的即可得到
哈夫曼编码就是根据它所在位置左为0右为1得到
编码长度根据所在位置相乘即可
总结
满二叉树圆圆慢慢,完全二叉树最后有缺
二叉树的先序遍历和后续遍历反映父节点和孩子节点间的层次关系
中序遍历反应兄弟节点间的次序关系
参考资料
《数据结构(Python版)》作者:吕云翔、郭颖美、孟爻
更多推荐










所有评论(0)