返回
操作树的结点- 从树中移除某个键
前端
2023-12-12 15:00:07
计算机体系中,树是一种非常重要的数据类型,我们前面学了如何插入一个结点,这篇文章我们来实现树的remove方法。
树的remove方法,又叫作删除(deletion)或者说摧毁(destruction)。 它有两种变种:
remove(key)
:删除一个特定的结点remove_subtree(key)
:删除一个子树
我们先来看第一个。 从树中删除一个特定的结点:
- 如果一个结点的键和要删除的结点的键相等,那么就删除它。
- 否则,比较结点和要删除的结点的键,依此递归删除树的左或右子树。
这里有一个需要注意的细节:在删除一个结点的时候,我们还需要更新结点的父结点的信息。在上面的这个算法中,我们没有做这个事情。这一般是根据树的实现来做的。 如果我们是把树作为一个数组来存储,那么父结点的索引就是结点索引整除以二。 如果结点的索引是偶数,那么它就是左结点,否则它是右结点。
func delete_node(tree, key):
# 寻找要删除结点
node = tree.find(key)
if node is None:
return
# 删除结点及其后代
def delete_subtree(node):
if node.left is None and node.right is None:
return
if node.left is None:
delete_subtree(node.right)
elif node.right is None:
delete_subtree(node.left)
else:
delete_subtree(node.left)
delete_subtree(node.right)
node.left = None
node.right = None
# 更新结点及其祖先结点的count
def update_node_count(node):
if node.left is None and node.right is None:
return 1
if node.left is None:
return 1 + update_node_count(node.right)
elif node.right is None:
return 1 + update_node_count(node.left)
else:
return 1 + update_node_count(node.left) + update_node_count(node.right)
delete_subtree(node)
update_node_count(node)
第一个是容易的,很容易实现。第二个是 difficult,因为有很多细节要考虑。我们这里简单的说一下。
- 如果一个结点有两个后代,那么我们只需要删除这个结点的后代。
- 如果一个结点只有一个后代,那么我们只需要删除这个结点的后代,然后把这个结点的后代的父结点设为这个结点的父结点。
- 如果一个结点没有后代,那么我们只需要从这个结点的父结点的children数组中删掉这个结点。