BST的形状为node
root的parent不存在git
假设元素的插入顺序为30,40,17,20,14 刚开始的时候没有元素,插入新的元素github
def insert(self,z):
x = self.root
y=None # x's parent
while x!=None :
//找到要插入的位置
y=x
if x.key <= z.key:
x=x.right
else:
x=x.left
if y == None:
//新插入的元素为第一个节点
self.root = z
z.parent = None
else:
//接入新的节点
z.parent = y
if y.key <= z.key:
y.right = z
else:
y.left = z
复制代码
它的耗时为O(lgn)bash
后继节点即从值上来说,找到比要找的元素要大最接近的值,根据BST的性质,它确定在右子树上,因此若是存在存在右子树,就是右子树上的最小值,不然回溯到父节点,直到父节点不存在,或者遇到第一个不存在右节点关系的父子节点即获得后继值ui
17的后继是20,即17的右子树的节点;spa
20的后继是30,因为20没有右子树,会先回溯到17,而后17是它的父节点的左子树,那么它就是后继节点;指针
40的后继不存在;code
def successor(self,node):
if node == None:
return None
if node.right != None:
# 后继必定在node的右节点
return self.minimum(node.right)
y = node.parent
# 后继节点只能在右节点
while y!=None and node == y.right:
node = y
y=y.parent
return y
复制代码
最小值则一直递归到左子树没有节点便可cdn
def minimum(self,node=None):
x = self.root if node == None else node
while x!=None and x.left!=None:
x = x.left
return x
复制代码
节点删除以后,必需要维持原有的BST性质blog
def delete(self,node):
if node.left == None:
# 若是node.right 是None 至关于把要删的节点直接置成None,不然 后继者必定是第一个right值
return self.transplant(node,node.right)
elif node.right == None:
# node.left 必定存在,只须要替换节点之间的指针
return self.transplant(node,node.left)
else:
# 左子树和右子树都有,要维持BST的性质,必须找到后继节点
successor = self.minimum(node.right)
if successor != node.right:
# 最小的左边的值必定不存在
self.transplant(successor,successor.right)
# right有变化
successor.right = node.right
# 修改原来节点的父节点 node.right 必定存在
successor.right.parent = successor
self.transplant(node,successor)
successor.left=node.left
# 修改原子节点的父节点 node.left必定存在
successor.left.parent = successor
return node
复制代码
指针变换关系为
def transplant(self,d,r):
""" d been delete r replecement"""
if d.parent == None:
self.root = r
elif d == d.parent.left:
d.parent.left = r
else:
d.parent.right = r
if r!=None:
r.parent = d.parent
return d
复制代码