假设我有一个数组作为输入,比如说
array = -1 0 0 1 2 1 3 5 5 6 6
(这实际上是二叉树的父数组表示)
在这种情况下,树看起来像这样:
0
/ \
1 2
/ \ /
3 5 4
/ / \
6 7 8
/ \
9 10
我有另一个输入,比如说
input = 1
(这是要从树中删除的节点)
我想要实现的基本上是:
这是我想到的删除节点及其所有子节点的算法。
所以基本上对于上面给出的样本输入,输出应该是:
-1 0 2
我选择不使用树数据结构,因为我觉得从父数组构造树,然后搜索节点并删除它可能会更慢(尽管我可能错了)。
我还没有能够在代码中实现这一点,我只是有逻辑。每当我尝试编写伪代码时,我的逻辑中的一个或多个问题就变得可见了。这就是为什么我没有具体的代码在这里发布。所以我不知道这需要多长时间。
这是一个类赋值的问题,只使用树数据结构就可以了,但是如果可能的话,我想在这种情况下实现更好的解决方案。
感谢任何帮助。无需给我完整的代码。只是一些指针就足够了。
答案 0 :(得分:2)
以下是算法略有修改版本的实现。
不同之处在于我们不会一个接一个地清除一个级别,而是一次性完成清除。这使用了这样一个事实,即孩子总是在他们父母的右边,所以如果我们只是通过列表一次并标记要删除的所有内容,我们就不会错过任何内容。
这使得树处于非规范状态,因为删除的节点仍然存在,它们只是标记为要删除(通过将其父项设置为-2
)。
因此,我还添加了一个opotional压缩步骤,删除这些节点并重新编号其余节点,以便其余节点编号为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]