1.树

树是一种数据结构 比如:目录结构
树是一种可以递归定义的数据结构
树是由n个节点组成的集合:
如果 n=0, 那这是一颗空树
如果 n>0, 那存在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一个树
一些概念:
根节点,叶子节点
树的深度(高度)
树的度:这个树中所有节点最大的度(孩子节点个数)
孩子节点/父节点
子树

2.用树简单模拟文件系统

"""
模拟文件系统
"""class Node:def __init__(self, name, type='dir'):self.name = nameself.type = typeself.children = []self.parent = Nonedef __repr__(self):return self.name# 链式存储方式class FileSystemTree:def __init__(self):self.root = Node("/")self.now = self.root  # 当前目录def mkdir(self, name):# name必须是一个文件夹,以"/"结尾if name[-1] != '/':name += "/"node = Node(name)self.now.children.append(node)node.parent = self.nowdef ls(self):print(self.now.children)def cd(self, name):if name[-1] != "/":name += "/"if name == "../":self.now = self.now.parentreturnfor child in self.now.children:if child.name == name:self.now = childbreakelse:raise ValueError("invalid dir.")tree = FileSystemTree()
tree.mkdir("var/")
tree.mkdir("bin")
tree.mkdir("usr")
print(tree.root.children)tree.ls()tree.cd("bin")
tree.mkdir("python")
tree.ls()tree.cd("../")
tree.ls()

3.二叉树

二叉树:度不超过二的树
二叉树的遍历方式:
前序遍历
中序遍历
后序遍历
层序遍历

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952"""
二叉树:度不超过二的树"""class BiTreeNode:def __init__(self, data):self.data = dataself.lchild = None  # 左孩子self.rchild = None  # 右孩子a = BiTreeNode('A')
b = BiTreeNode('B')
c = BiTreeNode('C')
d = BiTreeNode('D')
e = BiTreeNode('E')
f = BiTreeNode('F')
g = BiTreeNode('G')e.lchild = a
e.rchild = g
a.rchild = c
c.lchild = b
c.rchild = d
g.rchild = froot = eprint(root.lchild.rchild.data)"""
二叉树的遍历方式:前序遍历中序遍历后序遍历层序遍历
"""def pre_order(root):if root:print(root.data, end=',')pre_order(root.lchild)pre_order(root.rchild)pre_order(root)def in_order(root):if root:in_order(root.lchild)print(root.data, end=',')in_order(root.rchild)print()
in_order(root)def post_order(root):if root:post_order(root.lchild)post_order(root.rchild)print(root.data, end=',')print()
post_order(root)#利用队列实现
from collections import deque
def level_order(root):q = deque()if root:q.append(root)while len(q) > 0:node = q.popleft()print(node.data, end = ",")if node.lchild:q.append(node.lchild)if node.rchild:q.append(node.rchild)print()
level_order(root)"""
知道二叉树的前序遍历(或者后序遍历)和中序遍历,可以还原出这个二叉树
"""

知道二叉树的前序遍历(或者后序遍历)和中序遍历,可以还原出这个二叉树

4.二叉搜索树BST

二叉搜索树是一颗二叉树且满足性质:
任意节点上值为key
它的左子树上节点值都比key小
右子树上节点值都比key大
基本操作:
查询 O(logn)
插入 O(logn)
删除:
1.如果要删除的是叶子节点,直接删除
2.如果要删除的节点只有一个孩子,将此节点的父亲与孩子连接,然后删除该节点
如果要删除的节点是根,需要重新更新根节点
3.如果要删除的节点有两个孩子:将其右子树的最小节点删除,并替换当前节点

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952
"""
二叉搜索树是一颗二叉树且满足性质:任意节点上值为key它的左子树上节点值都比key小右子树上节点值都比key大
基本操作:查询 O(logn)插入 O(logn)删除:1.如果要删除的是叶子节点,直接删除2.如果要删除的节点只有一个孩子,将此节点的父亲与孩子连接,然后删除该节点如果要删除的节点是根,需要重新更新根节点3.如果要删除的节点有两个孩子:将其右子树的最小节点删除,并替换当前节点
"""
class BiTreeNode:def __init__(self, data):self.data = dataself.lchild = None  # 左孩子self.rchild = None  # 右孩子self.parent = Noneclass BST:def __init__(self, li=None):self.root = Noneif li:for val in li:self.insert_no_recur(val)def insert(self, node, val):if not node:node = BiTreeNode(val)elif val < node.data:node.lchild = self.insert(node.lchild, val)node.lchild.parent = nodeelif val > node.data:node.rchild = self.insert(node.rchild, val)node.rchild.parent = nodereturn nodedef insert_no_recur(self, val):p = self.rootif not p:  # 空树self.root = BiTreeNode(val)returnwhile True:if val < p.data:if not p.lchild:p.lchild = BiTreeNode(val)p.lchild.parent = preturnelse:p = p.lchildelif val > p.data:if not p.rchild:p.rchild = BiTreeNode(val)p.rchild.parent = preturnelse:p = p.rchildelse:returndef pre_order(self, root):if root:print(root.data, end=',')self.pre_order(root.lchild)self.pre_order(root.rchild)def in_order(self,root):if root:self.in_order(root.lchild)print(root.data, end=',')self.in_order(root.rchild)def post_order(self, root):if root:self.post_order(root.lchild)self.post_order(root.rchild)print(root.data, end=',')def query(self, node, val):if not node:  # 递归终止条件return Noneif node.data < val:return self.query(node.rchild, val)elif node.data > val:return self.query(node.lchild, val)else:return nodedef query_no_recur(self, val):p = self.rootwhile p:if p.data < val:p = p.rchildelif p.data > val:p = p.lchildelse:return pelse:return Nonedef __remove_node_1(self, node):# 1.node是叶子节点if not node.parent:  # node是根节点self.root = Noneelif node == node.parent.lchild:node.parent.lchild = Noneelse:node.parent.rchild = Nonedef __remove_node_21(self, node):# 2.node只有一个左孩子if not node.parent:  # 根节点self.root = node.lchildnode.lchild.parent = Noneelif node == node.parent.lchild:node.parent.lchild = node.lchildnode.lchild.parent = node.parentelse:node.parent.rchild = node.lchildnode.lchild.parent = node.parentdef __remove_node_22(self, node):# 3.node只有一个右孩子if not node.parent:self.root = node.rchildelif node == node.parent.lchild:node.parent.lchild = node.rchildnode.rchild.parent = node.parentelse:node.parent.rchild = node.rchildnode.rchild.parent = node.parentdef delete(self, val):if self.root:node = self.query_no_recur(val)if not node: # 不存在return Falseif not node.lchild and not node.rchild:self.__remove_node_1(node)elif not node.rchild:  # 2.1 只有一个左孩子self.__remove_node_21(node)elif not node.lchild:   #2.2 只有一个右孩子self.__remove_node_22(node)else:  # node有两个孩子min_node = node.rchildwhile min_node.lchild:min_node = min_node.lchildnode.data = min_node.data# 删除min_nodeif min_node.rchild:self.__remove_node_22(min_node)else:self.__remove_node_1(min_node)tree = BST([4,6,7,9,2,1,3,5,8])
tree.pre_order(tree.root)
print()
tree.in_order(tree.root)
print()
print(tree.query_no_recur(10))tree.delete(4)
tree.in_order(tree.root)"""
平均情况下,二叉搜索树查找的时间复杂度为O(logn)
最坏情况下,二叉树偏斜退化成一条链表,查找时间复杂度O(n)
解决方法:随机化插入AVL树
"""

平均情况下,二叉搜索树查找的时间复杂度为O(logn)
最坏情况下,二叉树偏斜退化成一条链表,查找时间复杂度O(n)
解决方法:
随机化插入
AVL树

5.自平衡二叉搜索树AVL

AVL树:是一棵自平衡的二叉搜索树
任意节点的左右子树高度差最大为1

如何保持平衡:旋转
插入一个节点后,只有从插入节点到根节点路径上的节点的平衡可能被破坏,
我们需要找出第一个破坏了平衡的节点,称之为K,K的两棵子树高度差为2
不平衡可能有4种情况:(右右左,左左右,左右左右,右左右左)
1.对K的右孩子的右子树插入导致的:左旋
2.对K的左孩子的左子树插入导致的:右旋
3.对K的右孩子的左子树插入导致的:右旋-左旋
4.对K的左孩子的右子树插入导致的:左旋-右旋

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952"""
AVL树:是一棵自平衡的二叉搜索树任意节点的左右子树高度差最大为1如何保持平衡:旋转插入一个节点后,只有从插入节点到根节点路径上的节点的平衡可能被破坏,我们需要找出第一个破坏了平衡的节点,称之为K,K的两棵子树高度差为2不平衡可能有4种情况:(右右左,左左右,左右左右,右左右左)1.对K的右孩子的右子树插入导致的:左旋2.对K的左孩子的左子树插入导致的:右旋3.对K的右孩子的左子树插入导致的:右旋-左旋4.对K的左孩子的右子树插入导致的:左旋-右旋
"""
from _027_二叉搜索树 import BiTreeNode, BSTclass AVLNode(BiTreeNode):def __init__(self, data):BiTreeNode.__init__(self, data)self.bf = 0  # balance factor = 右子树高度-左子树高度class AVLTree(BST):def __init__(self, li = None):BST.__init__(self, li)def rotate_left(self, p, c):s2 = c.lchildp.rchild = s2if s2:s2.parent = pc.lchild = pp.parent = cp.bf = 0c.bf = 0return cdef rotate_right(self, p, c):s2 = c.rchildp.lchild = s2if s2:s2.parent = pc.rchild = pp.parent = cp.bf = 0c.bf = 0return cdef rotate_right_left(self, p, c):# 先右旋g = c.lchilds3 = g.rchildc.lchild = s3if s3:s3.parent = cg.rchild = cc.parent = g# 再左旋s2 = g.lchildp.rchild = 2if s2:s2.parent = pg.lchild = pp.parent = g# 更新bfif g.bf > 0:p.bf = -1c.bf = 0elif g.bf < 0:p.bf = 0c.bf = 1else:  # 插入的是gp.bf = 0c.bf = 0g.bf = 0return gdef rotate_left_right(self, p, c):g = c.rchilds2 = g.lchildc.rchild = s2if s2:s2.parent = cg.lchild = cc.parent = gs3 = g.rchildp.lchild = s3if s3:s3.parent = pg.rchild = pp.parent = g# 更新bfif g.bf < 0:p.bf = 1c.bf = 0elif g.bf > 0:p.bf = 0c.bf = -1else:  # 插入的是gp.bf = 0c.bf = 0g.bf = 0return gdef insert_no_recur(self, val):# 1. 和BST一样,先插入p = self.rootif not p:  # 空树self.root = AVLNode(val)returnwhile True:if val < p.data:if not p.lchild:p.lchild = AVLNode(val)p.lchild.parent = pnode = p.lchildbreakelse:p = p.lchildelif val > p.data:if not p.rchild:p.rchild = AVLNode(val)p.rchild.parent = pnode = p.rchildbreakelse:p = p.rchildelse:  # val == p.data重复return# 2. 更新balance factorwhile node.parent:  # node的parent不空if node == node.parent.lchild:  # 传递是从左子树来的# 更新node的parent的bf -= 1if node.parent.bf < 0:  # 原来=-1,更新后变成-2,需要旋转了# 看node哪边沉,判断需要做哪种旋转g = node.parent.parent  # 为了连接旋转后的子树x = node.parent  # 旋转前子树的根if node.bf > 0:n = self.rotate_left_right(node.parent, node)else:n = self.rotate_right(node.parent, node)elif node.parent.bf > 0:  # 1, 更新后变成0,传递终止node.parent.bf = 0breakelse:  # 0, 更新后变-1node.parent.bf = -1node = node.parentcontinueelse:  # 传递是从右子树来的# 更新后node的parent的bf += 1if node.parent.bf > 0: # 1 -> 2, 需要旋转g = node.parent.parentx = node.parent  # 旋转前子树的根# 看node哪边沉if node.bf < 0:n = self.rotate_right_left(node.parent, node)else:n = self.rotate_left(node.parent, node)elif node.parent.bf < 0:  # -1 -> 0, 传递终止node.parent.bf = 0breakelse:  # 0->1node.parent.bf = 1node = node.parentcontinue# 连接旋转后的子树n.parent = gif g:if x == g.lchild:g.lchild = nelse:g.rchild = nbreakelse:self.root = nbreaktree = AVLTree([9,8,7,6,5,4,3,2,1])
print()
tree.pre_order(tree.root)
print()
tree.in_order(tree.root)"""
AVL树的应用--B树
B树是一个自平衡的多路搜索树,常用于数据库的索引,减少访问硬盘的次数
一个节点存放n个值,有n+1个子节点
"""

AVL树的应用–B树
B树是一个自平衡的多路搜索树,常用于数据库的索引,减少访问硬盘的次数
一个节点存放n个值,有n+1个子节点

五.树,二叉树,二叉搜索树(BST)和自平衡二叉搜索树(AVL)相关推荐

  1. 数据结构与算法(java):树-二叉树(二叉查找树(BST)、线索化二叉树、哈夫曼树、平衡二叉树【AVL】、二叉树的前中后序遍历)

    二叉树 1.定义 二叉树 就是度不超过2的树(每个结点最多只有两个子结点).如图 2.特殊二叉树 满二叉树 当二叉树的每一个层的结点树都达到最大值,则这个二叉树就是满二叉树. 完全二叉树 叶结点只能出 ...

  2. [二叉树遍历|BST]leetcode 538 把二叉搜索树转换为累加树

    [二叉树遍历|BST]leetcode 538 把二叉搜索树转换为累加树 1.题目 题目链接 给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree) ...

  3. 真c++ 从二叉树到红黑树(3)之二叉搜索树BST

      此文章为从二叉树到红黑树系列文章的第三节,主要介绍介绍二叉搜索树BST,为AVL和RedBlack打下基础 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.二叉搜索树BST的定义~ ...

  4. 有序二叉树c语言,二叉搜索树(BST)的实现(C语言)(原创)

    叉搜索树(Binary Search Tree)的一般形式如下图所示,每个节点中的元素大于它的左子树中的所有元素,小于它的右子树中的所有元素.对该图中的二叉树进行中序遍历得到一个从小到大排列的有序序列 ...

  5. 数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

    在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉 ...

  6. 真c++ 从二叉树到红黑树(4)之二叉平衡搜索树AVL

      此文章为从二叉树到红黑树系列文章的第四节,主要介绍介绍二叉平衡搜索树AVL,当你理解了AVL,红黑树你就理解了一半了! 文章目录 一.前面文章链接~(点击右边波浪线可以返回目录) 二.由BST引入 ...

  7. 看动画学算法之:二叉搜索树BST

    文章目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 看动画学算法之:二叉搜索树BST 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的 ...

  8. 二叉搜索树 (BST)

    二叉搜索树 (BST : Binary Search Tree) 又名 二叉查找树 或 二叉排序树. 二叉搜索树: 左孩子的值 一定小于或等于 父结点的值 二叉搜索树: 右孩子的值 一定大于或等于 父 ...

  9. 《恋上数据结构第1季》平衡二叉搜索树、AVL树

    AVL树 二叉搜索树缺点分析 改进二叉搜索树 平衡(Balance) 理想平衡 如何改进二叉搜索树? 平衡二叉搜索树(Balanced Binary Search Tree) AVL树 BST 对比 ...

最新文章

  1. VUE:class与style强制绑定
  2. HBase+Spark技术双周刊 第四期
  3. 活动助手Beta用户试用报告
  4. VTK:简单操作之DistanceBetweenPoints
  5. java面向对象:关键字 —(17)
  6. 阿里1682亿背后的协同研发云——云效公共云正式商业化 1
  7. python switch高效替代_python 中无switch(写了几个函数代替switch)
  8. java 开发微信中回调验证一直提示 解密失败处理(Java)
  9. mysql查询php输出表格_MySql数据库查询结果用表格输出PHP代码示例_PHP教程
  10. 工行基于MySQL构建分布式架构的转型之路
  11. 【数学建模】最优化模型
  12. oracle表重命名 索引,Oracle索引
  13. 下软件,就靠这几个网站
  14. Java集合--------16
  15. 线上故障之-CPU飙高
  16. mysql千万测试表生成,随机id、username、age、sex、create_time
  17. MPEG-TS封装格式数据
  18. 有师傅小程序开源版v2.4.14(含后端源码)
  19. 构建初级前端页面重构开发环境
  20. ERROR CoarseGrainedExecutorBackend: RECEIVED SIGNAL TERM

热门文章

  1. android动画 行星,Android自定义View之星球运动
  2. smc2.0默认服务器型号,可能导致华为视频会议SMC2.0系统安装不上的原因
  3. Java基础:对象序列化详解
  4. 使用Axure做验证码之获取验证码(一)
  5. SVG---矢量正五角星(喜迎国庆)
  6. linux安装音乐软件教程,Linux上好用的五款音乐播放器
  7. 爬取网易云音乐歌曲评论并生成特定词云图
  8. 在线压缩文档工具、迅捷压缩在线
  9. ashx 获取上传的文件_ashx文件获取$.ajax()方法发送的数据
  10. CSS 过渡 transition