在python中实现二叉搜索树删除时遇到问题
我实现了一个二叉搜索树的删除功能。其思想是声明一个私有函数,该函数使用一个额外的参数将在python中实现二叉搜索树删除时遇到问题,python,binary-search-tree,Python,Binary Search Tree,我实现了一个二叉搜索树的删除功能。其思想是声明一个私有函数,该函数使用一个额外的参数将self.root提取到root。在私有删除功能中,它将执行条件检查,并确保root等于需要删除的数据。在条件检查之后,我写下3种不同的删除情况。编译代码时没有错误消息,也没有删除任何插入的节点 class Node(object): def __init__(self, data, left=None, right=None, parent=None): self.left = lef
self.root
提取到root
。在私有删除功能中,它将执行条件检查,并确保root
等于需要删除的数据。在条件检查之后,我写下3种不同的删除情况。编译代码时没有错误消息,也没有删除任何插入的节点
class Node(object):
def __init__(self, data, left=None, right=None, parent=None):
self.left = left
self.data = data
self.right = right
class Tree(object):
def __init__(self):
self.root = Node(None)
def delete(self,newData):
if self.root.data == None:
print 'The tree is empty'
else:
self.__delete(self.root, newData)
def __delete(self, root, newData):
# if newData smaller than root.data, change root to root.left, recursive call
if newData < root.data:
if root.left:
self.__delete(root.left, newData)
else:
return False
# if newData larger than root.data, change root to root.right, recursive call
elif newData > root.data:
if root.right:
self.__delete(root.right, newData)
else:
return False
elif newData == root.data:
#case 1, root has no child
if root.left is None and root.right is None:
root = None
#case 2, root has one child (left)
elif root.left is not None and root.right is None:
root.data = root.left.data
root.left = None
#case 3, root has one child (right)
elif root.right is not None and root.left is None:
root.data = root.right.data
root.right = None
#case 4, root has both children,
# find the smallest node in the right subtree, and swipe value
# delete smallest node in the right subtree
else:
root.data = self.__minValueToRightSubtree(root.right).data
self.__deleteMinValueToRightSubtree(root.right)
else:
print "Can't find this number"
def __minValueToRightSubtree(self, root):
if root.left is None:
return root
else:
return self.__minValueToRightSubtree(root.left)
def __deleteMinValueToRightSubtree(self, root):
if root.left is None:
root = None
return root
else:
self.__minValueToRightSubtree(root.left)
类节点(对象):
def uuu init uuuu(self,data,left=None,right=None,parent=None):
self.left=左
self.data=数据
self.right=right
类树(对象):
定义初始化(自):
self.root=节点(无)
def delete(自我,新数据):
如果self.root.data==无:
打印“树为空”
其他:
self.\u删除(self.root,newData)
定义删除(self、root、newData):
#如果newData小于root.data,则将root更改为root.left,递归调用
如果newDataroot.data:
如果root.right:
self.\u delete(root.right,newData)
其他:
返回错误
elif newData==root.data:
#案例1,root没有子级
如果root.left为无,root.right为无:
根=无
#案例2,根目录有一个子目录(左)
elif root.left不是无,root.right是无:
root.data=root.left.data
root.left=无
#案例3,root有一个子级(右)
elif root.right不是None,root.left是None:
root.data=root.right.data
root.right=None
#案例4,root有两个孩子,
#在右子树中找到最小的节点,然后滑动值
#删除右子树中最小的节点
其他:
root.data=self.\uu minValueToRightSubtree(root.right).data
self.\uu删除MinValueToRightSubtree(root.right)
其他:
打印“找不到此号码”
def__minValueToRightSubtree(self,root):
如果root.left为无:
返回根
其他:
返回self.\uu minValueToRightSubtree(root.left)
def _deleteMinValueToRightSubtree(self,root):
如果root.left为无:
根=无
返回根
其他:
self._minValueToRightSubtree(根.左)
不幸的是,递归函数的基本情况都不能正常工作。有两种错误(每种错误重复两次,但有一些变化):
第一个问题相当简单。在案例2和案例3中,您从单个子节点复制数据,然后删除对该节点的引用。但是,如果子节点有自己的子节点,那么这样做是不对的。如果你的树保证是平衡的,也许你可以假设它没有子树,但是对于一般的BST,你不能这样假设。更好的版本是:
#case 2, root has one child (left)
elif root.left is not None and root.right is None:
root.data = root.left.data
root.right = root.left.right
root.left = root.left.left
#case 3, root has one child (right)
elif root.right is not None and root.left is None:
root.data = root.right.data
root.left = root.left.left
root.right = root.left.right
另一个问题更微妙。问题是,在案例1(以及案例4中的\u deleteMinValueToRightSubtree
帮助程序方法)中,您无法以尝试的方式删除根目录。您将<代码> NOT/CONT>分配给<代码>根<代码>,如果Python以C++和java DO(通过引用)的方式传递参数,则这可能会起作用。但是Python的参数与这些语言不同。Python参数是“通过赋值”传递的,这意味着函数中的参数是一个局部变量,绑定到调用方传入的同一对象。如果执行root=None
,则只修改局部变量,而不是树结构
有多种方法可以解决此问题。哪种方式最好将取决于实现的其他细节
如果节点
对象具有父节点
引用,则可以使用这些引用来取消节点与其父节点的链接(尽管对于没有父节点的根节点,您需要特殊情况)。我看到节点的构造函数有一个parent
参数,但您似乎没有使用它。如果将其连接起来,则删除节点的代码将相对容易
#case 1, root has no child
if root.left is None and root.right is None
if root.parent is None: # root is the root node of the whole tree
self.root = None
elif root.parent.left is root:
root.parent.left = None
else: # elif root.parent.right is root:
root.parent.right = None
#...
#case 4, root has both children,
# find the smallest node in the right subtree, and swipe value
# delete smallest node in the right subtree
else:
min_right_node = self.__minValueToRightSubtree(root.right)
root.data = min_right_node.data # no need to recurse twice
if min_right_node is self.right: # we can use the same node reference for
self.right = None # both steps (swiping value and deleting)
else:
min_right_node.parent.left = min_right_node.right
如果没有父链接,则可以改为更改递归的逻辑,以便返回修改后的树,调用者将该树分配给它正在递归的节点。这将要求您更改错误处理,因为返回值不是用于表示成功或失败的信号。如果找不到目标,我建议引发异常
def delete(self,newData):
if self.root.data == None: # should this be testing `self.root is None`?
print 'The tree is empty'
else:
self.root = self.__delete(self.root, newData) # use return value
def __delete(self, root, newData):
# if newData smaller than root.data, change root to root.left, recursive call
if newData < root.data:
if root.left:
root.left = self.__delete(root.left, newData)
else:
raise ValueError("Can't find this number")
# if newData larger than root.data, change root to root.right, recursive call
elif newData > root.data:
if root.right:
root.right = self.__delete(root.right, newData)
else:
raise ValueError("Can't find this number")
elif newData == root.data:
#case 1, root has no child
if root.left is None and root.right is None:
return None
#case 2, root has one child (left)
elif root.left is not None and root.right is None:
return root.left
#case 3, root has one child (right)
elif root.right is not None and root.left is None:
return root.right
#case 4, root has both children,
# find the smallest node in the right subtree, and swipe value
# delete smallest node in the right subtree
else:
root.right, root.data = __delete_min(root.right)
return root
else:
print "Can't find this number"
def __delete_min(self, root): # returns a (node, minimum value) 2-tuple
if root.left is None:
return root.right, root.data
else:
root.left, minval = self.__delete_min(root.left)
return root, minval
def delete(self,newData):
如果self.root.data==None:#这应该是在测试“self.root是None”吗?
打印“树为空”
其他:
self.root=self.u删除(self.root,newData)#使用返回值
定义删除(self、root、newData):
#如果newData小于root.data,则将root更改为root.left,递归调用
如果newDataroot.data:
如果root.right:
root.right=self.\u删除(root.right,newData)
其他:
raise VALUE ERROR(“找不到此号码”)
elif newData==root.data:
#案例1,root没有子级
如果root.left为无,root.right为无:
一无所获
#案例2,根目录有一个子目录(左)
elif root.left不是None,root.right是No