我有一个数字列表:
[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
我想避免构建一个树,然后计算每个节点的子节点数。必须有一种简单的数学方法来计算列表中的子数?
答案 0 :(得分:3)
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)
对于树是平衡的情况(即输入列表中的元素数量是奇数),可以使用以下公式计算:
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):
d = depth = floor(log2(1))+1 = 1
n_children = (7 - ((2^1)-1)) / 2^(1-1)
= (7 - 1) / 2^0
= 6 / 1
= 6
然后是数组位置1
,(即节点2):
d = depth = floor(log2(2))+1 = 2
n_children = (7 - ((2^2)-1)) / 2^(2-1)
= (7 - 3) / 2
= 2
对于i = 0到i = 6,继续给出[6,2,2,0,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)
答案 2 :(得分:1)
将第一个数组解释为堆,其中节点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]
答案 3 :(得分:0)
就像我们在堆中一样 子女[i] =所有孩子的子女总数+子女数
与第0个元素一样,[0] =其左子女的子女数+其子女的子女数+其子女数 所以a [0] = 2 + 2 + 2
for(int i=n-1;i>=0;i--) {
if(i*2+2 < n)
a[i]+=a[i*2+2]+1;
if(i*2+1 < n)
a[i]+=a[i*2+1]+1;
}