class TreeNode():
def __init__(self,key,val,left=None,right=None,parent=None):
self.key=key
self.payload=val
self.leftChild=left
self.rightChild=right
self.parent=parent
def hasLeftChild(self):
return self.leftChild
def hasRightChild(self):
return self.rightChild
def isLeftChild(self):
return self.parent and self.parent.leftChild==self
def isRightChild(self):
return self.parent and self.parent.rightChild == self
def isLeaf(self):
return not(self.leftChild or self.rightChild)
def hasAnyChild(self):
return self.leftChild or self.rightChild
def hasBothChild(self):
return self.rightChild and self.leftChild
def replaceNodeData(self,key,value,lc,rc):
self.key=key
self.payload=value
self.rightChild=rc
self.leftChild=lc
if self.hasLeftChild():
self.leftChild.parent=self
if self.hasRightChild():
self.rightChild=self
def findSuccessor(self):
'''寻找后继结点'''
succ=None
if self.hasRightChild():
succ=self.rightChild.findMin()
else:
if self.parent:
if self.isLeftChild():
succ=self.parent
else:
self.parent.rightChild=None
succ=self.parent.findSuccessor()
self.parent.rightChild=self
return succ
def findMin(self):
current=self
while current.hasLeftChild():
current=current.leftChild
return current
def spliceOut(self):
if self.isLeaf(): #叶子节点
if self.isLeftChild: #是左孩子
self.parent.leftChild=None
else: #是右孩子
self.parent.rightChild=None
elif self.hasAnyChild():
if self.hasLeftChild():
if self.isLeftChild():
self.parent.leftChild=self.leftChild
else:
self.parent.rightChild=self.leftChild
self.leftChild.parent=self.parent
else:
if self.isLeftChild():
self.parent.leftChild=self.rightChild
else:
self.parent.rightChild=self.rightChild
self.rightChild.parent=self.parent
class BinarySearchTree:
def __init__(self):
self.root=None
self.size=0
def length(self):
return self.size
def __len__(self):
return self.size
def __iter__(self):
return self.root.__iter__()
def put(self,key,val):
'''为BST插入新节点'''
if self.root:
self._put(key,val,self.root)
else:
self.root=TreeNode(key,val)
self.size+=1
def _put(self,key,val,currentNode):
if key<currentNode.key:
#递归处理左子树
if currentNode.hasLeftChild():
self._put(key,val,currentNode.leftChild)
else: #如果没有左孩子则插入到这个节点的左孩子上(递归出口)
currentNode.leftChild=TreeNode(key,val,parent=currentNode)
else:
#递归处理右子树
if currentNode.hasRightChild():
self._put(key,val,currentNode.rightChild)
else:
currentNode.rightChild=TreeNode(key,val,parent=currentNode)
def __setitem__(self, key, value):
'''调用put方法来重载运算符[],可以像字典一样添加节点'''
self.put(key,value)
def get(self,key):
'''查找键对应的值'''
if self.root: #树不为空
res=self._get(key,self.root)
if res: #如果找到了
return res.payload
else:
return None
else:
return None
def _get(self,key,currentNode):
if not currentNode: #如果currentNode为空节点
return None
elif currentNode.key==key: #找到了这个key(递归出口)
return currentNode
elif key<currentNode.key: #如果key比当前节点的key小则在左子树上找
self._get(key,currentNode.leftChild)
else: #否则在右子树上找
return self._get(key,currentNode.rightChild)
def __getitem__(self, item):
'''可以像字典一样查找二叉树'''
return self.get(item)
def __contains__(self, item):
'''此方法重载了运算符 in 检查树中是否有某个键'''
if self._get(item,self.root):
return True
else:
return False
def createByDict(self,dict):
'''用字典构建BST'''
for key,value in dict.items():
self.put(key,value)
def createByList(self,list):
'''用列表构建BST,值为None'''
for key in list:
self.put(key,None)
def delete(self,key):
if self.size>1: #不只有根节点
nodeToRemove=self._get(key,self.root)
if nodeToRemove: #找到这个节点,删除并返回
self.remove(nodeToRemove)
self.size-=1
return nodeToRemove
else: #找不到这个节点抛出异常
raise KeyError('Error,key not in tree')
elif self.size==1 and self.root.key==key: #只有一个根节点并且根节点就是要找的key
nodeToRemove=self.root
self.root=None
self.size-=1
return nodeToRemove
else: #只有一个根节点但不是要找的key,抛出异常
raise KeyError('Error,key not in tree')
def __delitem__(self, key):
'''使对象可以用del删除key'''
self.delete(key)
def remove(self,currentNode):
if currentNode.isLeaf(): #叶子节点
if currentNode.isLeftChild:
currentNode.parent.leftChild=None
else:
currentNode.parent.rightChild=None
elif currentNode.hasBothChild(): #内部
succ=currentNode.findSuccessor()
succ.spliceOut()
currentNode.key=succ.key
currentNode.payload=currentNode.payload
else: #只有一个子节点
if currentNode.hasLeftChild():
if currentNode.isLeftChild():
currentNode.leftChild.parent=currentNode.parent
currentNode.parent.leftChild=currentNode.leftChild
elif currentNode.isRightChild():
currentNode.leftChild.parent=currentNode.parent
currentNode.parent.rightChild=currentNode.leftChild
else:
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild)
else:
if currentNode.isLeftChild():
currentNode.rightChild.parent=currentNode.parent
currentNode.parent.leftChild=currentNode.rightChild
elif currentNode.isRightChild():
currentNode.rightChild.parent=currentNode.parent
currentNode.parent.rightChild=currentNode.rightChild
else:
currentNode.replaceNodeData(currentNode.rightChild.key,
currentNode.rightChild.payload,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChil)
二叉搜索树(BST)
最新推荐文章于 2025-12-18 10:59:28 发布
1128

被折叠的 条评论
为什么被折叠?



