我正在尝试编写一个代码来删除BST的所有节点(每个节点只有三个属性,左,右和数据,没有父指针) . 下面的代码是我提出的,它只删除树的右半部分,保持左半部分完好无损 . 如何修改它以便左半部分也被删除(这样我最终只剩下没有左或右子树的根节点)?
def delete(root):
global last
if root:
delete(root.left)
delete(root.right)
if not (root.left or root.right):
last = root
elif root.left == last:
root.left = None
else:
root.right = None
其次,任何人都可以建议使用堆栈或其他相关数据结构的迭代方法吗?
4 回答
Blckknght对垃圾收集是正确的,但是如果你想做一些比你的例子建议更复杂的清理或者理解为什么你的代码不起作用,我会提供一个额外的答案:
您的问题似乎是
elif node.left == last
检查 .我不确定你的
last
变量用于什么或它背后的逻辑是什么 .但问题是
node.left
几乎永远不会等于last
(如果两个子节点都已设置为None
,则它们只将一个节点分配给last
变量,它们不适用于任何有趣的节点(那些有子节点的节点)) .如果查看代码,您会看到,如果
node.left
不等于last
,则只有右子项设置为None
,因此只删除子树的右侧部分 .我不知道python,但这应该工作:
(我冒昧地将
root
参数重命名为node
,因为赋予该函数的节点不必是树的根节点 . )如果要删除两个子树,则无需递归 . 只需将
root.left
和root.right
设置为None
并让垃圾收集器处理它们 . 实际上,你可以设置root = None
而不是首先制作一个delete
函数!Edit: 如果你需要在数据值上运行清理代码,你可能想要通过树递归来获取所有这些代码,如果GC确实没有必要,但我也会这样做:
您还询问了遍历树的迭代方法,这有点复杂 . 这是一种使用
deque
(作为堆栈)跟踪祖先的遍历方法:使用堆栈的迭代后序遍历可能如下所示:
do_something
会执行您想要调用的任何内容"actually deleting this node" .你可以更简单地通过在每个节点上设置一个属性来说明它是否已经调用
do_something
,但是如果你的节点有__slots__
或其他什么,你显然不能很好地工作,你不想要修改节点类型以允许标志 .在递归调用之后,我不确定你对这些条件做了什么,但我认为这应该足够了:
正如评论中指出的那样,Python不会通过引用传递参数 . 在这种情况下,你可以在Python中使用这样的工作:
至于迭代方法,你可以试试这个 . 它是伪代码,我不知道python . 基本上我们做BF搜索 .
同样,如果您将其用作函数,则默认情况下不会修改根,但它将删除所有其他节点 . 您可以在函数调用后将根设置为None,或者删除参数并处理全局根变量 .