【问题标题】:Delete a node and all of its children from a binary tree, without using a tree data structure从二叉树中删除一个节点及其所有子节点,而不使用树数据结构
【发布时间】:2018-04-02 21:19:28
【问题描述】:

假设我有一个数组作为输入,比如说

数组 = -1 0 0 1 2 1 3 5 5 6 6

(这实际上是二叉树的父数组表示)

在这种情况下,树看起来像这样:

         0
       /   \
      1     2
     / \   /
    3   5 4
   /   / \
  6   7   8
 / \
9  10

我还有另一个输入,比如说

输入 = 1

(这是要从树中删除的节点)

我想要达到的基本上是:

  1. 删除数组[输入]
  2. 在剩余数组中搜索输入变量
  3. 删除所有 value = input 的元素
  4. 存储已删除值的索引
  5. 在剩余的数组中搜索 value = indices
  6. 删除这些元素并存储它们的索引
  7. 从第 5 步开始重复,直到无法删除任何内容

这是我想到的删除节点及其所有子节点的算法。

所以基本上对于上面给出的示例输入,输出应该是:

-1 0 2

我选择不使用树数据结构,因为我觉得从父数组构造树,然后搜索节点并删除它可能会更慢(尽管我可能错了)。

虽然我无法在代码中实现这一点,但我只有逻辑。每当我尝试编写伪代码时,我的逻辑中的一个或多个问题就会显现出来。这就是为什么我还没有具体的代码可以在这里发布的原因。所以我不知道这需要多长时间。

这是一个关于类分配的问题,只使用树数据结构就可以了,但如果可能的话,我想在这种情况下实现更好的解决方案。

感谢任何帮助。无需给我完整的代码。只需一些指针就足够了。

【问题讨论】:

  • 我认为您的方法的问题在于步骤 2/5 在每次迭代中具有线性复杂性。当然,您可以在线性时间内一劳永逸地为孩子制作地图,然后在恒定时间内查找,但这将构建一个除了名称之外的所有树结构。
  • 根据您的表述,从树中删除一个项目是什么意思?如果您想删除5,您在列表中的索引5 中添加什么?您是否需要更新78,或者之后它们仍然可以指向已删除的节点?如果“删除”一个节点会重新编号所有连续的节点名称(通过移动它们在列表中的索引),您将需要进行大量清理工作以使其他所有内容仍然可以组合在一起。
  • @Blckknght,我不需要更新树中的任何值,但正如我在问题中所说,如果我要删除一个节点,我需要删除它的所有子节点。因此,删除 5、7 和 8 也会被删除。清理没那么重要。在我分配的问题中,重要的是删除节点。该操作只执行一次,无需清理。
  • @Paul Panzer,有没有更好的方法呢?
  • Yuki.kuroshita,想一想我觉得可能有办法,我会尽力解答。顺便提一句。我认为@Blckknght 有一点:-1 0 2 似乎不是一个有效的表示,因为按照位置等于子 id 约定,它必须被读作 0:没有父,1:父是 0,2:父是 2。

标签: python arrays python-2.7 tree binary-tree


【解决方案1】:

这是您的算法稍作修改的版本。

不同之处在于,我们不是一个接一个地进行清除,而是一次性完成。这利用了孩子总是在他们父母的右边这一事实,所以如果我们只浏览一次列表并标记要删除的所有内容,我们就不会错过任何内容。

这会使树处于非规范状态,因为已删除的节点仍然存在,它们只是被标记为要删除(通过将其父节点设置为 -2)。

因此,我还添加了一个可选的压缩步骤,删除这些节点并重新编号剩余的节点,以便剩余的节点编号为 0、1、2、... 没有间隙。

from itertools import islice, count

def delete_branch_from_tree(parents, branch_root,
                            compress=False, inplace=False):
    n = len(parents)
    if not inplace: # make a copy
        parents = parents[:]
    if branch_root == 0:
        parents[:] = [] if compress else n * [-2]
        return parents
    # -2 will indicate missing nodes
    parents[branch_root] = -2
    for node in range(branch_root+1, n):
        if parents[parents[node]] == -2:
            parents[node] = -2
    if compress: # remove nodes marked as missing, renumber the other ones
        c = count()
        new_number = [None if parent==-2 else next(c) for parent in parents]
        parents[:] = [new_number[parent] for parent in parents if parent != -2]
        # -1 was not in the lookup table (new_number), must fix manually
        parents[0] = -1
    return parents

演示:

>>> tree = [-1, 0, 0, 1, 2, 1, 3, 5, 5, 6, 6]
>>> 
>>> delete_branch_from_tree(tree, 1)
[-1, -2, 0, -2, 2, -2, -2, -2, -2, -2, -2]
>>> delete_branch_from_tree(tree, 1, compress=True)
[-1, 0, 1]
>>> delete_branch_from_tree(tree, 5)
[-1, 0, 0, 1, 2, -2, 3, -2, -2, 6, 6]
>>> delete_branch_from_tree(tree, 5, compress=True)
[-1, 0, 0, 1, 2, 3, 5, 5]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多