二叉搜索树
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树
平衡二叉搜索树
平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
代码
class BiTreeNode:
def __init__(self,data):
self.data=data
self.lchild=None
self.rchild=None
self.parent=None
class BST:
def __init__(self,li=None):
self.root=None
if li:
for val in li:
self.insert_no_rec(val)
#插入
def insert(self,node,val): #递归
if not node: #node为空
node=BiTreeNode(val)
elif val< node.data:
node.lchild=self.insert(node.lchild,val)
node.lchild.parent=node
elif val>node.data:
node.rchild=self.insert(node.rchild,val)
node.rchild.parent=node
return node
def insert_no_rec(self,val): #不递归
p=self.root
if not p:
self.root=BiTreeNode(val)
return
while True:
if val<p.data:
if p.lchild:
p=p.lchild
else:
p.lchild=BiTreeNode(val)
p.lchild.parent=p
return
elif val>p.data:
if p.rchild:
p=p.rchild
else:
p.rchild=BiTreeNode(val)
p.rchild.parent=p
return
else:
return
#遍历
def pre_order(self,root):
if root: # 递归终止条件
print(root.data, end=',')
self.pre_order(root.lchild)
self.pre_order(root.rchild)
#查找
def query(self,node,val): #递归
if not node:
return None
if node.data<val:
return self.query(node.rchild,val)
elif node.data>val:
return self.query(node.lchild,val)
else:
return node
#删除
# 情况一:node是叶子结点
def __remove_node_1(self,node):
if not node.parent: # node.parent为空,只有根的父节点为空,即当前节点为根节点的时候,进行以下操作
self.root=None
if node ==node.parent.lchild: #node是父节点的左孩子
node.parent.lchild=None
else:
node.parent.rchild=None
#情况二:node只有一个左孩子
def __remove_node_21(self,node):
if not node.parent: #如果要删除的节点为根节点
self.root=node.lchild #更新根节点为原来的左孩子
node.lchild.parent=None #左孩子现在为根节点,没有父节点
elif node==node.parent.lchild: #要删除的节点为父节点的左孩子
node.parent.lchild=node.lchild #更新父节点的左孩子为当前节点的左孩子
node.lchild.parent=node.parent #更新左孩子的父节点为当前节点的父节点
else: #要删除的节点为其父节点的右孩子
node.parent.rchild=node.lchild
node.lchild.parent=node.parent
#情况三:node只有一个右节点
def __remove_node_22(self,node):
if not node.parent:
self.root=node.rchild
node.rchild.parent=None
elif node ==node.parent.lchild:
node.parent.lchild=node.rchild
node.rchild.parent=node.parent
else:
node.parent.rchild=node.rchild
node.rchild.parent=node.parent
def delete(self,val):
if self.root: #不是空树
node=self.query_no_rec(val)
if not node: #不存在
return False
if not node.lchild and not node.rchild: #1.左右孩子都为空,即叶子结点
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: #3.3左右孩子都有
min_node=node.rchild #找到右孩子最小的节点
while min_node.lchild:
min_node=min_node.lchild
node.data=min_node.data
#删除min_node
if min_node.rchild: #如果有右节点(min_node肯定没有叶子结点)
self.__remove_node_22(min_node)
else:
self.__remove_node_1(min_node)
def query_no_rec(self,val): #不使用递归
p=self.root
while p:
if p.data<val:
p=p.rchild
if p.data>val:
p=p.lchild
else:
return p
return None
class AVLNode(BiTreeNode):
def __init__(self,data):
BiTreeNode.__init__(self,data)
self.bf=0
class AVLTree(BST):
def __init__(self,li=None):
BST.__init__(self,li)
def ratate_left(self,p,c): #左旋
s2=c.lchild
p.rchild=s2
if s2:
s2.parent=p
c.lchild=p
p.parent=c
p.bf=0
c.bf=0
return c
def ratate_right(self,p,c): #右旋
s2=c.rchild
p.lchild=s2
if s2:
s2.parent=p
c.rchild=p
p.parent=c
p.bf=0
c.bf=0
return c
def ratate_right_left(self,p,c):
g=c.lchild
s3=g.rchild
c.lchild=s3
if s3:
s3.parent=c
g.rchild=c
c.parent=g
s2=g.lchild
p.rchild=s2
if s2:
s2.parent=p
g.lchild=p
p.parent=g
#更新bf
if g.bf>0:
p.bf=-1
c.bf=0
elif g.bf<0:
p.bf=0
c.bf=1
else: #插入的是g
p.bf=0
c.bf=0
def ratate_left_right(self,p,c) :
g=c.lchild
s2=g.lchild
c.rchild=s2
if s2:
s2.parent=c
g.lchild=c
c.parent=g
s3=g.rchild
p.lchild=s3
if s3:
s3.parent=p
g.rchild=p
p.parent=g
#更新bf
if g.bf<0:
p.bf=1
c.bf=0
elif g.bf>0:
p.bf=0
c.bf=-1
else:
p.bf=0
c.bf=0
def insert_no_rec(self,val):
#1.和BST一样,插入
p=self.root
if not p: #空树
self.root=AVLNode(val)
return
while True:
if val<p.data:
if p.child:
p=p.lchild
else:
p.lchild=AVLNode(val)
p.lchild.parent=p
node=p.lchild
break
elif val>p.data:
if p.rchild:
p=p.rchild
else:
p.rchild=AVLNode(val)
p.rchild.parent=p
node=p.rchild
break
else:
return
#2.更新balance factor
while node.parent: #node.parent不空
if node.parent.lchild==node: #传递是从左子树来的,左子树更沉了
#更新node.parent的bf-=1
if node.parent.bf<0: #原来的node.bf=-1,更新后变成-2
#做旋转
#看哪边更沉
g=node.parent.parent #为了连接旋转之后的子树
x = node.parent # 旋转前子树的根
if node.bf>0: #先左旋后右旋
n=self.ratate_left_right(node.parent,node)
else:
n=self.ratate_right(node.parent,node)
#记得:把n和g连接起来
elif node.parent.bf<0: #原来node.parent.bf=1,更新后变成0
node.parent.bf=0
break
else: #原来node.parent.bf=0,更新后变成-1
node.parent.bf=-1
node=node.parent
continue
else: #传递是从右边来的,右子树更沉了
#更新后的node.parent.bf+=1
if node.parent.bf>0: #原来node.parent.bf=1,更新后变成2
#做旋转
# 看哪边更沉
g = node.parent.parent # 为了连接旋转之后的子树
x=node.parent #旋转前子树的根
if node.bf < 0: # node.bf=1
n = self.ratate_right_left(node.parent, node)
else:
n = self.ratate_left(node.parent, node)
# 记得:把n和g连接起来
elif node.parent.bf < 0: # 原来node.parent.bf=-1,更新后变成0
node.parent.bf = 0
break
else: # 原来node.parent.bf=0,更新后变成1
node.parent.bf = 1
node = node.parent
continue
#连接旋转后的子树
n.parent=g
if g: #g不空
if x==g.lchild:
g.lchild=n
else:
g.rchild=n
break
else:
self.root=n
break
tree=AVLTree([1,2,3,4,5,6,7,8,9])
tree.pre_order(tree.root)
print()
tree.pre_order(tree.root)