提问人:Muhammad Olamide 提问时间:11/7/2023 更新时间:11/7/2023 访问量:17
BST删除方法运行不正常
BST delete method not functioning well
问:
所以我对二叉搜索树很不满意,现在即使是人工智能也无法帮助解决这个特定问题,我想这是一个逻辑遗漏的问题。删除方法无法正常工作,我需要帮助。tree.delete(2) 应该删除 2 和 2 应该在末尾打印,但它仍然打印 2。我会喜欢提供的任何帮助。
class BstNode:
def __init__(self, val=None) :
self.val = val
self.left = None
self.right = None
def insert(self, val):
if self.val == None:
self.val = val
elif self.val == val:
print("Duplicate Value")
return
elif val > self.val:
if self.right == None:
self.right = BstNode(val)
else:
self.right.insert(val)
elif val < self.val:
if self.left == None:
self.left = BstNode(val)
else:
self.left.insert(val)
# the init_call values are for the print just to debug, has no uses after this to print full list after all recursive call
def preorder(self, visited=None, init_call=True):
if visited is None:
visited = []
visited.append(self.val)
if self.left:
self.left.preorder(visited, False)
if self.right:
self.right.preorder(visited, False)
if init_call: # Check if this is the initial call to the function
print(visited)
return visited
def postorder(self, visited=None, init_call=True):
if visited is None:
visited = []
if self.left:
self.left.postorder(visited, False)
if self.right:
self.right.postorder(visited, False)
visited.append(self.val)
if init_call: # Check if this is the initial call to the function
print(visited)
return visited
# in order from lowest to highest
def inorder(self, visited=None, init_call=True):
if visited is None:
visited = []
if self.left:
self.left.inorder(visited, False)
visited.append(self.val)
if self.right:
self.right.inorder(visited, False)
if init_call: # Check if this is the initial call to the function
print(visited)
return visited
def print(self):
if self.left:
self.left.print()
if self.val !=None:
print(self.val)
if self.right:
self.right.print()
def get_min(self):
if self.left is None:
print(self.val)
return self.val
return self.left.get_min()
def get_max(self):
if self.right is None:
print (self.val)
return self.val
return self.right.get_max()
def exist(self, val):
if self.val == val:
return True
if self.right and val > self.val:
return self.right.exist(val)
elif self.left and val < self.val:
return self.left.exist(val)
return False
def height(self):
if self.val is None:
return 0
left_height = 0
right_height = 0
if self.left:
left_height= self.left.height()
if self.right:
right_height= self.right.height()
return 1 + max(left_height, right_height)
def delete(self, val):
if self.val is None:
return self
elif val < self.val:
if self.left:
self.left = self.left.delete(val)
elif val > self.val:
if self.right:
self.right = self.right.delete(val)
else:
if self.right is None:
temp = self.left
del self
return temp
elif self.left is None:
temp = self.right
del self
return temp
else:
temp = self.right.findMin()
self.val = temp.val
self.right = self.right.delete(temp.val)
return self
def findMin(self):
current = self
while current.left is not None:
current = current.left
return current
def fill_tree(tree, num_range = 10, max_int = 100):
from random import randint
tree.insert(35)
for _ in range( num_range):
cur_element = randint(0, max_int)
tree.insert(cur_element)
return tree
tree = BstNode()
tree.insert(2)
tree.insert(5)
tree.insert(7)
tree.insert(10)
tree.insert(20)
tree.insert(35)
print("_________PRINT________________")
tree.print()
print("_________PREORDER________________")
tree.preorder()
print("_________POSTORDER________________")
tree.postorder()
print("_________INORDER________________")
tree.inorder()
print("_________GETMIN________________")
tree.get_min()
print("_________GETMAX________________")
tree.get_max()
print("_________EXISIT________________")
print(tree.exist(35))
print("_________HEIGHT________________")
print(tree.height())
tree.delete(2)
tree.delete(5)
tree.delete(7)
tree.delete(10)
tree.delete(20)
tree.delete(35)
print("_________PRINT________________")
tree.print()
2-3 天后,我设法理解并编译了这段代码
打印 shhould 在末尾不打印任何内容,但仍然打印两个,表明打印在两个上不起作用,因为 2 是应该在左侧末尾的最低值。我将不胜感激所提供的所有帮助。
答:
问题在于,当您的函数在第一次调用时检测到(根)节点具有要删除的值(即 2),它会返回一个子节点引用,但返回的引用“无处可去”:您的主程序不查看返回的内容,而只是期望工作完成。此外,没有做任何有用的事情,至少对树没有。那只是解除了名称的束缚。所以什么都没有改变 -- 没有删除任何节点。delete
delete
del self
一个快速的解决方法是在你拥有它的两个地方都用替换。这至少“清除”了节点,使其处于“僵尸”状态。如果它恰好是根节点,则将被视为已删除,即使它仍然是对该节点的引用。del self
self.val = None
tree
尽管这解决了您眼前的问题,但使用相同的类来表示树和节点是一个糟糕的设计选择。结果是,你需要把这个“无效”节点视为一个神奇的值,因为你没有一种干净的方式来表示一棵空树——你的方法要求总是至少有一个节点,因为这是你对树的引用。因此,要表示一棵空树,您需要创建一个值为 .这导致了很多问题,导致代码需要始终检查当前节点是否可能是这样的“僵尸”节点。您的代码并不总是这样做,因此仍然存在错误(例如在 中)。None
None
exists
但是,我建议创建第二个类,,其属性为(当树为空时)或对根节点的引用(实例)。然后将您需要的所有方法添加到该类中 -- 如果相关,它们可以将此类调用转发给。但重要的优势是,现在你可以真正表示一棵空树,并且不需要代码来检测和管理“僵尸”节点。它还有助于为您的方法编写优雅的代码,这些代码可以非常简洁,因为它们可以依赖于类中具有相同名称的方法。Bst
root
None
BstNode
BstNode
Bst
BstNode
这是我的一个答案,它提出了这种设计,并带有代码。
评论
None
.exists(None)