Data structures 完全二叉树作为一种高效的数据结构
您将得到一个大小为n的数组(n是2的幂)。数组的所有条目都初始化为零。您必须执行以下一系列联机操作:Data structures 完全二叉树作为一种高效的数据结构,data-structures,binary-tree,Data Structures,Binary Tree,您将得到一个大小为n的数组(n是2的幂)。数组的所有条目都初始化为零。您必须执行以下一系列联机操作: Add(i,x)将x添加到条目A[i] Reportsum(i,j)=数组中从索引i到j的条目之和。对于任何01)(也称为i/2),第三个数组中的索引(i>>2)(也称为i/4),等等 诀窍在于计算总和(i,j)。我们现在要计算sum(0,j)和sum(0,i-1),因为sum(i,j)=sum(0,j)-sum(0,i-1) 要计算总和(0,v)(对于某些v),您所要做的就是从每个级别最多添加
Add(i,x)
将x
添加到条目A[i]
sum(i,j)
=数组中从索引i
到j
的条目之和。对于任何0
为了提高效率,我选择了一个数组,其中第一个数组大小为n,下一个数组大小为n/2,n/4,n/8。。。1.无论何时向[i](第一个数组)添加x,都会将其添加到第二个数组中的索引(i>>1)(也称为i/2),第三个数组中的索引(i>>2)(也称为i/4),等等
诀窍在于计算总和(i,j)。我们现在要计算sum(0,j)和sum(0,i-1),因为sum(i,j)=sum(0,j)-sum(0,i-1)
要计算总和(0,v)(对于某些v),您所要做的就是从每个级别最多添加一个条目。从0到索引*求和的伪代码(不包括索引本身)如下所示:
sum from 0 to index:
begin
i = 0
sum = 0
while i < maxlevel
if ((index >> i) & 1) != 0
sum = sum + array[i][index]
return sum
end
从0到索引的总和:
开始
i=0
总和=0
而我却不知道
如果((索引>>i)&1)!=0
总和=总和+数组[i][index]
回报金额
结束
要直观地了解这一点,请考虑最低级别的数组,并从0求和到偶数索引和奇数索引。如果您使用的是偶数索引,您可以通过使用它上面的数组来更有效地执行此操作,因为它已经将每两个条目相加了!实际上,对于奇数索引,您只需执行与偶数索引相同的操作,只需手动添加一个“奇数人”条目。但是,由于您将在第二个级别对索引进行求和,您可以只做最后一个(如果要求和的新索引是奇数的话)之外的所有操作。。等等等等等等。。这正是我们在这里所做的
这些应该是你需要的全部了。如果你想用二叉树,你仍然可以用同样的方式。您可以在二叉树的每个节点中保留一个和。在遍历以将和添加到特定节点时,还要将其添加到所遍历的所有节点。同样,您也可以使用查找零索引的相同技巧。查找从零到索引的和现在变成了一个二叉树遍历,其中对于您遍历的每个节点,添加节点的和,然后减去您正在而不是遍历的任何“右侧”(或更高的值)子节点
希望我没有破坏家庭作业的问题,通过阅读本文,你有足够的兴趣来完成它,但不会太多,问题现在被简单化为仅仅实现
祝你好运 树解决方案:
创建一棵完整的树,它的叶子是你的主菜:1,2,…,n
node.value=插入值[如果节点是叶]
node.value=node.left.value+node.right.value[如果节点不是叶子]
所以,实际上-对于每个子树,其根的值是其所有节点的值之和
更新主菜是O(logn),因为您需要一直更新到根的总和
对于sum(i,j),我们将找到i之前所有元素的和,以及j之前所有元素的和,然后从root.value中减去它,我们将得到我们需要的。
因此:
sumleet()
和sumlright()
的计算很简单,[对于sumleet:]只需从根开始,一直到下限,每次向左,都要减去right-son值,这样做,就可以从不需要的节点中求和。[说服自己为什么这是真的]。最后,总和只有相关节点。[sumRight的原理相同,但我们会减去left sons]。
伪代码:
sumLeft(x,root):
curr <- root
sum <- root.value
while (curr is not a leaf):
if (x is in curr.right):
curr <- curr.right
else:
sum <- sum - curr.right.value
curr <- curr.left
return sum
sumRight(x,root):
curr <- root
sum <- root.value
while (curr is not a leaf):
if (x is in curr.left):
curr <- curr.left
else:
sum <- sum - curr.left.value
curr <- curr.right
return sum
总结示例:
总和(4,6)应提供4+6+1=11
。
sumlefit(4)应提供1+3+2=6
,并按预期提供:sumlefit(4)=21-11-4=6
。
sumRight(6)应该提供2+2=4
,它提供sumLeft(6)=21-11-7=4
。[如预期的那样]
因此,总的来说:sum(4,6)=21-6-4=11
与预期一致
添加示例:
添加(2,4)[将4添加到第二个元素]将导致将树修改为:
25
14 11
8 6 7 4
1 7 2 4 6 1 2 2
我已经为[n]创建了一个段树,其中根包含[I,j],如果我能告诉我如何插入元素,请给出一个10个元素的示例。@rohit:我编辑了解释如何向主菜添加值的答案。注:我不能给出10个元素的例子,因为问题清楚地表明n是2的幂,而10不是。稍后我将能够提供一个包含8个元素的示例树。您已经给出了一个非常好的解决方案,但我认为在您的[code]leftsum(x,root)[/code]和rightsum(x,root)中,如果我将left(x-1,root)right(x+1,root)[请记住,如果x-1n不计算rightsum并将其作为零],那么您的psudo代码工作得非常好。如果我是Worong,请纠正我。@rohit:这是一个伪代码,我调试它不是为了查看所有的边缘情况。但是你提到的似乎是正确的。。。我只给了你一般的指导,要使它成为一个完整的家庭作业解决方案,还需要深入到边缘案例。祝你好运
add(root,i,x):
root.value <- root.value + x
if root is leaf:
return
else if i is in root.left:
add(root.left,i,x)
else:
add(root.right,i,x)
21
10 11
4 6 7 4
1 3 2 4 6 1 2 2
25
14 11
8 6 7 4
1 7 2 4 6 1 2 2