[英]Binary search tree deletion function in Python
I'm beginner in Python and I tried to create a function to delete a node in a binary search tree.我是 Python 初学者,我尝试创建一个函数来删除二叉搜索树中的节点。
I tried calling .delete
on a node.我尝试在节点上调用
.delete
。 The node is a leaf node with no children so it should be deleted.该节点是没有子节点的叶节点,因此应将其删除。 However, after I called
.delete
, the node is still there.但是,在我调用
.delete
,该节点仍然存在。
This is the code:这是代码:
class Node:
def __init__(self,key):
self.left = None
self.right = None
self.val = key
#some functions for insert etc.
def delete(self, key):
"""DELETE"""
try:
if self is None:
print("Tree is empty.")
return None
else:
if key < self.val:
self.left.delete(key)
elif key > self.val:
self.right.delete(key)
else:
#this seems to be the problem
if self.left is None :
temp = self.right
#print(self, self.val, self.right)
self = temp
return
elif self.right is None :
temp = self.left
self = temp
return
temp = minValue(self.right)
self.val = temp.val
self.right.delete(temp.val)
except(AttributeError):
print("There's no such number in a tree.")
def inorder(root):
if root is not None:
inorder(root.left)
print(root.val, end=" ")
inorder(root.right)
def minValue(node):
current = node
while(current.left is not None):
current = current.left
return current
r = Node(50)
After inserting numbers 30 20 40 70 60 80
to r
and calling inorder(r)
I get: 20 30 40 50 60 70 80
, which corresponds to the tree将数字
30 20 40 70 60 80
插入到r
并调用inorder(r)
我得到: 20 30 40 50 60 70 80
,它对应于树
50
/ \
30 70
/ \ / \
20 40 60 80
but after r.delete(30)
, I get: 20 40 40 50 60 70 80
, which is:但在
r.delete(30)
,我得到: 20 40 40 50 60 70 80
,即:
50
/ \
40 70
/ \ / \
20 40 60 80
The value to delete is replaced correctly but the used node ( 40
) without children should be deleted.要删除的值已正确替换,但应删除没有子节点的已使用节点 (
40
)。
What may be the reason of such a problem?出现这种问题的原因可能是什么?
Simply put, you cannot assign anything to self
.简而言之,您不能为
self
分配任何内容。 In Python, self
is a reference to the object that you called the method on.在 Python 中,
self
是对调用方法的对象的引用。 It would not be None
(so you don't need the if self is None
check), and you cannot assign some other value to it.它不会是
None
(因此您不需要if self is None
检查),并且您不能为其分配其他值。
However, when deleting a node from the tree, it is possible that the current node (the node which you called delete
on) will be deleted.但是,从树中删除节点时,可能会删除当前节点(您调用
delete
的节点)。 Instead of assigning values to self
, we can make the delete
return a node object.我们可以让
delete
返回一个节点对象,而不是给self
赋值。 If the current node is not deleted, simply return itself;如果当前节点没有被删除,直接返回自身; otherwise, return the node the will take its place (or
None
if the entire subtree is gone).否则,返回将取代其位置的节点(如果整个子树都消失了,则返回
None
)。
Here's the modified implementation, along with an insert
method and a test case:这是修改后的实现,以及一个
insert
方法和一个测试用例:
class Node:
def __init__(self, key):
self.left = self.right = None
self.val = key
def delete(self, key):
"""Delete a node with value `key`."""
if key < self.val:
# Find and delete the value in the left subtree.
if self.left is None:
# There's no left subtree; the value does not exist.
raise ValueError("Value not found in tree")
self.left = self.left.delete(key)
return self # current node not deleted, just return
elif key > self.val:
# Find and delete the value in the right subtree.
if self.right is None:
# There's no right subtree; the value does not exist.
raise ValueError("Value not found in tree")
self.right = self.right.delete(key)
return self # current node not deleted, just return
else:
# The current node should be deleted.
if self.left is None and self.right is None:
# The node has no children -- it is a leaf node. Just delete.
return None
# If the node has only one children, simply return that child.
if self.left is None:
return self.right
if self.right is None:
return self.left
# The node has both left and right subtrees, and they should be merged.
# Following your implementation, we find the rightmost node in the
# left subtree and replace the current node with it.
parent, node = self, self.left
while node.right is not None:
parent, node = node, node.right
# Now, `node` is the rightmost node in the left subtree, and
# `parent` its parent node. Instead of replacing `self`, we change
# its attributes to match the value of `node`.
if parent.left is node:
# This check is necessary, because if the left subtree has only
# node, `node` would be `self.left`.
parent.left = None
else:
parent.right = None
self.val = node.val
return self
def insert(self, key):
if key < self.val:
if self.left is None:
self.left = Node(key)
else:
self.left.insert(key)
else:
if self.right is None:
self.right = Node(key)
else:
self.right.insert(key)
def inorder_traverse(node):
if node is None:
return []
ret = []
if node.left is not None:
ret += inorder_traverse(node.left)
ret.append(node.val)
if node.right is not None:
ret += inorder_traverse(node.right)
return ret
values = [5, 1, 2, 7, 3, 6, 4]
root = Node(values[0])
for x in values[1:]:
root.insert(x)
print(inorder_traverse(root))
for x in values:
root = root.delete(x)
print(inorder_traverse(root))
The output is, as expected:正如预期的那样,输出是:
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 6, 7]
[2, 3, 4, 6, 7]
[3, 4, 6, 7]
[3, 4, 6]
[4, 6]
[4]
[]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.