在接受采访时我问过这个问题。我们如何转换BT,使其中的每个节点都具有一个值,该值是其子节点的总和?
答案 0 :(得分:3)
为每个节点提供附加值。构造树时,设置叶子的值;构造内部节点以具有值leaf1.value + leaf2.value
。
如果您可以更改叶节点的值,那么操作必须“备份”更新总和值的树。
如果要么在节点中包含反向链接,要么将树实现为“threaded tree”,这将会容易得多。
答案 1 :(得分:2)
这是一个可以帮助您的解决方案:(链接用树形图解释)
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以查看完整的解决方案和说明!
答案 2 :(得分:2)
正如Charlie指出的那样,您可以简单地在每个内部节点中存储各个子树大小的总和,并在构造时提供常量值(或者如果您只对叶子数量感兴趣,则始终隐式使用1)在树上)。
这通常称为增强搜索树。
有趣的是,通过这种扩充,即存储额外的每节点数据,您还可以为树中的项目导出其他类型的聚合信息。您可以将任何信息表示为可以存储在扩充树中的幺半群,为此,您需要指定:
除了子树大小之外,您还可以表达以下内容:
(这个概念让人联想到堆,或更明确的treaps,它将内部节点的随机优先级存储在概率平衡中。它也常见于Finger Trees的上下文中,尽管这些并不相同。)< / p>
如果你还为你的幺半群提供了一个中性元素,那么你可以走下这样一个幺半群增强的搜索树来检索特定的元素(例如,“找到我的第5片叶子”为你的大小例子;“给我叶子具有最高优先级“)。
不管怎么说,呃。可能会在那里被带走......我碰巧发现这个话题非常有趣。 :)答案 3 :(得分:1)
以下是总和问题的代码。它的工作原理我测试了它。
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;
}
答案 4 :(得分:0)
使用递归函数,您可以通过使每个节点的值等于其子节点的值的总和,条件是它有两个子节点,或者它的单个子节点的值(如果它有一个子节点),并且如果它没有子(叶子),那么这就是破坏条件,值永远不会改变。