Algorithm 如何数树上的孩子

Algorithm 如何数树上的孩子,algorithm,Algorithm,我有一个数字列表: [1, 2, 3, 4, 5, 6, 7] 我感兴趣的是找到一种算法,如果列表中的树: 1 / \ 2 3 / \ / \ 4 5 6 7 我正在寻找一种算法,它将给出: [6,

我有一个数字列表:

[1, 2, 3, 4, 5, 6, 7]
我感兴趣的是找到一种算法,如果列表中的树:

                              1
                            /   \
                           2     3
                          / \   / \
                         4   5 6   7
我正在寻找一种算法,它将给出:

[6, 2, 2, 0, 0, 0, 0]


A = 6
B = 2
C = 2
D = 0
E = 0
F = 0
G = 0
每个节点(叶除外)有两个子节点。唯一的例外是,如果列表中出现以下情况:

                              1
                            /   \
                           2     3
                          / \   / 
                         4   5 6   
我希望避免构建一棵树,然后计算每个节点上的子节点数。必须有一种简单的数学方法来计算列表中的子级数?

1-对数组进行索引

然后对于索引为i的节点,左边的子节点的索引为2*i,右边的子节点的索引为2*i+1

然后从头到尾检查阵列,现在检查节点:

若他的(左或右)子的索引超出数组的界限,那个么他并没有(左或右)子

如果没有,那么你可以知道他儿子的孩子的数量(我们从那时开始遍历数组)。结果=现在儿子的孩子数量+现在儿子的数量

例如:

[1, 2, 3, 4, 5, 6, 7]
A is the result array.
1.A=[0, 0, 0, 0, 0, 0, 0],now(now is a index) = 7(1-indexed) since 7*2>7, a[7]=0
2.A=[0, 0, 0, 0, 0, 0, 0],now = 6,since 6*2>7, a[6]=0
3.A=[0, 0, 0, 0, 0, 0, 0],now = 5,since 5*2>7, a[5]=0
4.A=[0, 0, 0, 0, 0, 0, 0],now = 4,since 4*2>7, a[4]=0
5.A=[0, 0, 2, 0, 0, 0, 0],now = 3,since 3*2<7 and 3*2+1<7, a[3]=2+a[6]+a[7]=2
6.A=[0, 2, 2, 0, 0, 0, 0],now = 2,since 2*2<7 and 2*2+1<7, a[2]=2+a[4]+a[5]=2
7.A=[6, 2, 2, 0, 0, 0, 0],now = 1,since 1*2<7 and 1*2+1<7, a[1]=2+a[2]+a[3]=6
[1,2,3,4,5,6,7]
A是结果数组。
1.A=[0,0,0,0,0,0,0],现在(现在是索引)=7(1-索引),因为7*2>7,A[7]=0
2.A=[0,0,0,0,0,0,0],现在=6,因为6*2>7,A[6]=0
3.A=[0,0,0,0,0,0,0],现在=5,因为5*2>7,A[5]=0
4.A=[0,0,0,0,0,0,0],现在=4,因为4*2>7,A[4]=0

5.A=[0,0,2,0,0,0,0],现在=3,因为3*2将第一个数组解释为堆,其中节点n的子节点位于2*n+1和2*n+2,然后递归地遍历树:

def children(t, n):
    if 2 * n + 1 >= t:
        return 0
    elif 2 * n + 2 >= t:
        return 1
    else:
        return 2 + children(t, 2 * n + 1) + children(t, 2 * n + 2)

size = 7
childcounts = [ children(size, i) for i in range(size) ]
print(childcounts)
这将打印:


[6,2,2,0,0,0,0]

对于平衡树的情况(即输入列表中的元素数为奇数),可以使用以下公式计算:

n = length of elements in input list
然后对于输出列表中的元素
i

d = depth of element in tree = floor(log2(i+1))+1
那么树中该元素下的子元素数为:

n_children = n - ((2^d)-1) / 2^(d-1)
对于[1,2,3,4,5,6,7]的例子:

n = 7
对于阵列位置
0
(即节点1):

然后对于然后的阵列位置
1
,(即节点2):

如果继续这样做,i=0到i=6将得到[6,2,2,0,0,0]

这方面的Python代码如下所示:

import math

def n_children(list_size, i):
    depth = math.floor(math.log(i+1,2)) + 1
    return (list_size - ((2**depth)-1)) / 2**(depth-1)

print [n_children(7, i) for i in range(7)]
这将输出
[6.0,2.0,2.0,0.0,0.0,0.0,0.0]

处理偶数输入数组需要一些修改(最简单的方法可能是将数组大小四舍五入到最接近的奇数,然后从
i
或类似的奇数值中减去1)。

就像我们在堆中做的那样, children[i]=其所有子项的子项之和+子项数

与第0个元素一样,[0]=其左子元素的子元素数+其右子元素的子元素数+其子元素数 所以a[0]=2+2+2

用于(inti=n-1;i>=0;i--){
如果(i*2+2 如果(i*2+1
}

这不是真的-参见示例(2的儿子是4和6,而不是4和5)。为什么树看起来像您示例中的树?具体来说,为什么5不是2的儿子而不是6?如何将数组转换为树?在您的示例中,从根开始,然后是l(eft)节点,十个r(右)节点,然后是ll,然后是rl,然后是lr,然后是rr,接下来是什么?lll,rll,lrl,rrl,llr,rlr,lrr,rrr?基本上先是下一代的所有左节点,然后是下一代的右节点?谢谢。我在原始树中有一个错误。@Gal我假设他在任意节点上生成任意树,并且子树结构是由BFS生成的。只有在数据结构中,树才被视为有根的和有序的,通常情况下不必如此。@在构建/更改树时,您可以跟踪所需的信息,只需使用反映该信息的计数器增加节点,并在更改时,将更改传播到根。这将与需要更改计数器的插入/删除/旋转/(无论更改树的结构如何)操作的复杂性相同。当然,列表的后半部分将始终为零,对于范围内的i(大小//2)
,您实际上只需要
…即可。
d = depth = floor(log2(2))+1 = 2
n_children = (7 - ((2^2)-1)) / 2^(2-1)
           = (7 - 3) / 2
           = 2
import math

def n_children(list_size, i):
    depth = math.floor(math.log(i+1,2)) + 1
    return (list_size - ((2**depth)-1)) / 2**(depth-1)

print [n_children(7, i) for i in range(7)]