AVL树:AVL树是一棵自平衡的二叉搜索树
AVL树具有与以下性质:
根的左右子树高度差的绝对值不超过1
根的左右子树都是平衡二叉树


插入一个节点可能会破坏AVL树的平衡,可以通过旋转操作来进行修正。
插入一个节点后,只有从插入节点到根节点的路径上的节点平衡可能被改变。我们需要找出第一个破坏了平衡条件的节点,称之为K。K的两颗子树的高度查2。
不平衡的出现可能有4中情况。
旋转口诀:
对于K,右右->左旋,左左->右旋,右左->右左,左右->左右




1、需引用二叉搜索树
# -*- encoding= utf-8 -*-from bst_new import BiTreeNode,BSTclass AVLNode(BiTreeNode):def __init__(self,data):BiTreeNode.__init__(self,data)#self.bf=0 #此处的self.bf添加到BiTreeNode.__inint__中去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=gs2=g.lchildp.rchild=s2if 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=0return g #返回根节点def 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:c.bf=0p.bf=1elif g.bf>0:p.bf=0c.bf=-1else: #插入的是gp.bf=0c.bf=0return gdef insert_no_rec(self,val):# 1、和二叉搜索(bst)数一样,插入p=self.rootif not p: #空树时,直接定义个二叉树根节点self.root=BiTreeNode(val)returnwhile True:if val<p.data:if p.lchild: #此处可看出与递归的方式的区别p=p.lchildelse: #左孩子不存在p.lchild=BiTreeNode(val)p.lchild.parent=pnode=p.lchild #node存储的是插入的节点breakelif val>p.data:if p.rchild:p=p.rchildelse:p.rchild=BiTreeNode(val)p.rchild.parent=pnode=p.rchildbreakelse: # val=p.datareturn#2、更新bfwhile node.parent: #node.parent不空if node.parent.lchild==node:#传递是从左子树来的,左子树更沉了#更新node.parent的bf -=1if node.parent.bf <0: #原来node.parent.bf=-1,更新之后变成-2#做旋转#看node哪边沉x=node.parent #旋转前的子树的根g=node.parent.parent #为了连接旋转之后的子树if node.bf>0:n=self.rotate_left_right(node.parent,node)else:n=self.rotate_right(node.parent,node)# 记得把n和g连起来elif node.parent.bf>0: #原来node.parent.bf=1,更新之后变成0node.parent.bf=0breakelse: #原来node.parent.bf=0,更新之后变成-1node.parent.bf=-1node=node.parentcontinueelse:#传递是从右子树来的,右子树更沉了#更新node.parent.bf+=1if node.parent.bf>0: #原来node.parent.bf=1,更新之后变成2#做旋转#看node哪边沉g=node.parent.parentx=node.parent #旋转前的子树的根if node.bf<0: #node.bf= -1n=self.rotate_right_left(node.parent,node)else: #node.bf= 1n=self.rotate_left(node.parent,node)# 记得连起来elif node.parent.bf<0: #原来node.parent.bf=-1,更新之后变成0node.parent.bf=0breakelse: #原来node.parent.bf=0,更新之后变成1node.parent.bf=1node=node.parentcontinue#连接旋转后的子树n.parent=gif g: #g不是空if x==g.lchild:g.lchild=nelse:g.rchild=nbreakelse:self.root=nbreaktree=AVLTree([9,8,7,6,5,4,3,2,1])tree.pre_order(tree.root)print("")tree.in_order(tree.root)
