#Created By: Chen Da
#构造一个树节点的类
#以此作为BinarySearchTree的引用
class TreeNode(object):
def __init__(self,key,value,left=None,right=None,parent=None):
self.key = key
self.value = value
self.leftChild = left
self.rightChild = left
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 isRoot(self):
return not self.parent
def isLeaf(self):
return not (self.leftChild or self.rightChild)
def hasAnyChildren(self):
return self.leftChild or self.rightChild
def hasBothChildren(self):
return self.leftChild and self.rightChild
def replaceNodeData(self,key,value,leftChild,rightChild):
self.key = key
self.value = value
self.leftChild = leftChild
self.rightChild = rightChild
if self.isLeftChild():
self.parent.leftChild = self
if self.isRightChild():
self.parent.rightChild = self
#定义二叉搜索树类(很像Python的字典)
class BinarySearchTree(object):
def __init__(self):
self.root = None
self.size = 0
def __len__(self):
return self.size
def length(self):
return self.size
def __iter__(self):
return self.root.__iter__()
def put(self,key,value):
"""
此方法用来检查树是否具有根。
如果没有根,那么put将创建一个新的TreeNode并将其做为树的根。
如果根节点已经就位,则put调用私有递归辅助函数_put根据以下算法搜索树:
1、从树的根开始,搜索二叉树,将新键与当前节点中的键进行比较。如果新键小于当前节点,则搜索左子树。如果新键大于当前节点,则搜索右子树。
2、当没有左(或右)孩子要搜索时,我们在树种找到应该建立新节点的位置。
3、要向树种添加节点,请创建一个新的TreeNode对象,并将对象插入到上一步发现的节点。
"""
if self.root:
self._put(key,value,self.root)
else:
self.root = TreeNode(key,value)
self.size += 1
def _put(self,key,value,currentNode):
if key < currentNode.key:
if currentNode.hasLeftChild():
self._put(key,value,currentNode.leftChild)
else:
currentNode.leftChild = TreeNode(key,value,parent=currentNode)
else:
if currentNode.hasRightChild():
self._put(key,value,currentNode.rightChild)
else:
currentNode.rightChild = TreeNode(key,value,parent=currentNode)
def __setitem__(self, key, value):
self.put(key,value)
def get(self,key):
'''
类似Python字典根据键取值
:param key:
:return:
'''
if self.root:
result = self._get(key,self.root)
if result:
return result.value
else:
return None
else:
return None
def _get(self,key,currentNode):
if not currentNode:
return None
elif currentNode.key == key:
return key
elif key < currentNode.key:
return 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 delete(self,key):
if self.size > 1:
nodeToRemove = self._get(key,self.root)
if nodeToRemove:
self.remove(nodeToRemove)
self.size -= 1
else:
raise KeyError("Error,key not in tree!")
elif self.size == 1 and self.root.key == key:
self.root = None
self.size -= 1
else:
raise KeyError("Error,not in the tree!")
def __delitem__(self, key):
self.delete(key)
def spliceOut(self):
if self.isLeaf():
if self.isLeftChild():
self.parent.leftChild = None
else:
self.parent.rightChild = None
elif self.hasAnyChildren():
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
def findSuccessor(self):
'''
寻找后继。利用二叉搜索树的相同属性,采用中序遍历从最小到最大打印树中的节点。
需要考虑三种情况:
1、如果节点有右子节点,则后继节点是右子树中的最小的键
2、如果节点没有右子节点并且是父节点的左子节点,则父节点是后继节点
3、如果节点是其父节点的右子节点,并且其本身没有右子节点,则此节点的后继节点是其父节点的后继节点,不包括此节点。
:return:
'''
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 remove(self,currentNode):
if currentNode.isLeaf(): #要删除的节点没有子节点
if currentNode == currentNode.parent.leftChild:
currentNode.parent.leftChild = None
else:
currentNode.parent.rightChild = None
elif currentNode.hasBothChild(): #要删除的节点有两个子节点
succ = currentNode.findSuccessor()
succ.spliceOut()
currentNode.key = succ.key
currentNode.value = succ.value
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.replaeNodeData(currentNode.leftChild.key,
currentNode.leftChild.value,
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.value,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChild)
19_数据结构与算法_查找树_Python实现
猜你喜欢
转载自blog.csdn.net/PyDarren/article/details/83928462
今日推荐
周排行