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)]