删除 BST 中有两个 children 的节点
Deleting a node with two children in BST
我已经实现了一个二叉搜索树,它工作正常,除了我必须删除一个有两个 children 的节点的情况。以下是我的删除方法代码:
def find(self, node):
curr = node
while curr.left is not None:
curr = curr.left
return curr
def delete(self, key):
node_to_remove = self._search(key, self.root)
if node_to_remove.left is None and node_to_remove.right is None:
#Then we identify this as a leaf node
if node_to_remove is node_to_remove.parent.left:
#Setting the parent's reference to this to None
node_to_remove.parent.left = None
elif node_to_remove is node_to_remove.parent.right:
node_to_remove.parent.right = None
#2nd Case --> Two child
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
node_to_remove = minimum
self.delete(minimum.key)
#3rd Case -> One child
else:
if node_to_remove.left:
node_to_remove.left.parent = node_to_remove.parent
node_to_remove.parent.left = node_to_remove.left
elif node_to_remove.right:
node_to_remove.right.parent = node_to_remove.parent
node_to_remove.parent.right = node_to_remove.right
关于如何解决第二种情况的任何指标都将提供巨大帮助!
您需要获取更深的已删除节点的值并将其分配给具有两个子节点的节点。所以那个块应该是这样的:
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
self.delete(minimum.key)
node_to_remove.key = minimum.key
其他备注
当根具有要删除的值并且它没有两个子项时,您的代码将 运行 进入异常。在这种情况下,您的代码想要访问根节点没有的父节点。此外,这样的删除应该导致 this.root
.
的不同值
这是建议的更正:
def delete(self, key):
node_to_remove = self._search(key, self.root)
if node_to_remove.left is None and node_to_remove.right is None:
if node_to_remove is self.root:
self.root = None
elif node_to_remove is node_to_remove.parent.left:
node_to_remove.parent.left = None
elif node_to_remove is node_to_remove.parent.right:
node_to_remove.parent.right = None
#2nd Case --> Two child
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
self.delete(minimum.key)
node_to_remove.key = minimum.key
#3rd Case -> One child
else:
if node_to_remove.left:
node_to_remove.left.parent = node_to_remove.parent
if node_to_remove is self.root:
self.root = node_to_remove.left
else:
node_to_remove.parent.left = node_to_remove.left
elif node_to_remove.right:
node_to_remove.right.parent = node_to_remove.parent
if node_to_remove is self.root:
self.root = node_to_remove.right
else:
node_to_remove.parent.right = node_to_remove.right
第二个评论:你的树是线程化的(即它有 parent
个引用)。可以对 non-threaded 树执行此操作,而且代码更少。
我已经实现了一个二叉搜索树,它工作正常,除了我必须删除一个有两个 children 的节点的情况。以下是我的删除方法代码:
def find(self, node):
curr = node
while curr.left is not None:
curr = curr.left
return curr
def delete(self, key):
node_to_remove = self._search(key, self.root)
if node_to_remove.left is None and node_to_remove.right is None:
#Then we identify this as a leaf node
if node_to_remove is node_to_remove.parent.left:
#Setting the parent's reference to this to None
node_to_remove.parent.left = None
elif node_to_remove is node_to_remove.parent.right:
node_to_remove.parent.right = None
#2nd Case --> Two child
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
node_to_remove = minimum
self.delete(minimum.key)
#3rd Case -> One child
else:
if node_to_remove.left:
node_to_remove.left.parent = node_to_remove.parent
node_to_remove.parent.left = node_to_remove.left
elif node_to_remove.right:
node_to_remove.right.parent = node_to_remove.parent
node_to_remove.parent.right = node_to_remove.right
关于如何解决第二种情况的任何指标都将提供巨大帮助!
您需要获取更深的已删除节点的值并将其分配给具有两个子节点的节点。所以那个块应该是这样的:
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
self.delete(minimum.key)
node_to_remove.key = minimum.key
其他备注
当根具有要删除的值并且它没有两个子项时,您的代码将 运行 进入异常。在这种情况下,您的代码想要访问根节点没有的父节点。此外,这样的删除应该导致 this.root
.
这是建议的更正:
def delete(self, key):
node_to_remove = self._search(key, self.root)
if node_to_remove.left is None and node_to_remove.right is None:
if node_to_remove is self.root:
self.root = None
elif node_to_remove is node_to_remove.parent.left:
node_to_remove.parent.left = None
elif node_to_remove is node_to_remove.parent.right:
node_to_remove.parent.right = None
#2nd Case --> Two child
elif node_to_remove.left and node_to_remove.right:
minimum = self.find(node_to_remove.right)
self.delete(minimum.key)
node_to_remove.key = minimum.key
#3rd Case -> One child
else:
if node_to_remove.left:
node_to_remove.left.parent = node_to_remove.parent
if node_to_remove is self.root:
self.root = node_to_remove.left
else:
node_to_remove.parent.left = node_to_remove.left
elif node_to_remove.right:
node_to_remove.right.parent = node_to_remove.parent
if node_to_remove is self.root:
self.root = node_to_remove.right
else:
node_to_remove.parent.right = node_to_remove.right
第二个评论:你的树是线程化的(即它有 parent
个引用)。可以对 non-threaded 树执行此操作,而且代码更少。