【发布时间】:2011-03-20 17:49:20
【问题描述】:
这个问题是在一次采访中问我的。我们如何转换一个 BT 使得其中的每个节点都有一个值是它的子节点的总和?
【问题讨论】:
-
好吧,如果他们只能存储子节点的总和,他们都只会存储值 0。最终,树的叶子没有子节点,所以它们的总和为 0,因此向上通过树全为零。 :)
标签: c++ c data-structures binary-tree
这个问题是在一次采访中问我的。我们如何转换一个 BT 使得其中的每个节点都有一个值是它的子节点的总和?
【问题讨论】:
标签: c++ c data-structures binary-tree
给每个节点一个附加值。当你构造树时,叶子的值就设置好了;构造内部节点以具有值leaf1.value + leaf2.value。
如果您可以更改叶节点的值,则操作必须“备份”树更新总和值。
如果您在节点中包含反向链接,或者将树实现为“threaded tree”,这将容易得多。
【讨论】:
这里有一个可以帮助你的解决方案:(链接用树形图解释)
Convert an arbitrary Binary Tree to a tree that holds Children Sum Property
/* This function changes a tree to to hold children sum
property */
void convertTree(struct node* node)
{
int left_data = 0, right_data = 0, diff;
/* If tree is empty or it's a leaf node then
return true */
if(node == NULL ||
(node->left == NULL && node->right == NULL))
return;
else
{
/* convert left and right subtrees */
convertTree(node->left);
convertTree(node->right);
/* If left child is not present ten 0 is used
as data of left child */
if(node->left != NULL)
left_data = node->left->data;
/* If right child is not present ten 0 is used
as data of right child */
if(node->right != NULL)
right_data = node->right->data;
/* get the diff of node's data and children sum */
diff = left_data + right_data - node->data;
/* If node's data is smaller then increment node's data
by diff */
if(diff > 0)
node->data = node->data + diff;
/* THIS IS TRICKY --> If node's data is greater then increment left
subtree by diff */
if(diff < 0)
increment(node->left, -diff);
}
}
查看link查看完整的解决方案和解释!
【讨论】:
正如查理指出的那样,您可以简单地将各个子树大小的总和存储在每个内部节点中,并让叶子在构造时提供常量值(或者如果您只对叶子的数量感兴趣,则始终隐式使用 1在树上)。
这通常称为增强搜索树。
有趣的是,通过这种增强,即存储额外的每个节点数据,您还可以为树中的项目导出其他类型的聚合信息。任何可以表示为幺半群的信息都可以存储在增强树中,为此,您需要指定:
所以除了子树大小之外,您还可以表达如下内容:
(这个概念很容易让人联想到堆,或者更明确地说是堆,它使用内部节点存储随机优先级以实现概率平衡。它在手指树的上下文中也很常见,尽管它们不是一回事。)
如果你还为你的幺半群提供了一个中性元素,那么你可以沿着这样一个幺半群增强的搜索树来检索特定元素(例如,“为你的大小示例找到第 5 片叶子”;“给我叶子具有最高优先级”)。
嗯,无论如何。那里可能有点忘乎所以。我只是碰巧发现这个话题很有趣。 :)
【讨论】:
这是求和问题的代码。它的工作原理我已经测试过。
int sum_of_left_n_right_nodes_4m_root(tree* local_tree){
int left_sum = 0;
int right_sum = 0;
if(NULL ==local_tree){
return 0;
}
if((NULL == local_tree->left)&&(NULL == local_tree->right)){
return 0;
}
sum_of_left_n_right_nodes(local_tree->left);
sum_of_left_n_right_nodes(local_tree->right);
if(NULL != local_tree->left)
left_sum = local_tree->left->data +
local_tree->left->sum;
if(NULL != local_tree->right)
right_sum = local_tree->right->data + \
local_tree->right->sum;
local_tree->sum= right_sum + left_sum;
}
【讨论】:
使用递归函数,您可以通过使每个节点的值等于在它有两个孩子的情况下它的孩子的值的总和,或者如果它有一个孩子,它是单个孩子的值,并且如果它没有孩子(叶子),那么这是破坏条件,值永远不会改变。
【讨论】: