二叉树,其中每个节点的值包含子节点的总和

时间:2011-03-20 17:49:20

标签: c++ c data-structures binary-tree

在接受采访时我问过这个问题。我们如何转换BT,使其中的每个节点都具有一个值,该值是其子节点的总和?

5 个答案:

答案 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)在树上)。

这通常称为增强搜索树。

有趣的是,通过这种扩充,即存储额外的每节点数据,您还可以为树中的项目导出其他类型的聚合信息。您可以将任何信息表示为可以存储在扩充树中的幺半群,为此,您需要指定:

  1. 数据类型M;在你的例子中,整数
  2. 用于组合元素的二元运算“op”,其中M op M - >米;在您的示例中,常见的“加号”运算符
  3. 除了子树大小之外,您还可以表达以下内容:

    • 优先级(通过“min”或“max”运算符),用于有效查询最小/最大优先级;
    • 子树中最右边的元素(即,只是返回其第二个参数的“op”运算符),前提是存储在树中的元素以某种方式排序。请注意,这使我们甚至可以查看常规搜索树(也就是字典 - “将此存储,检索该密钥”)作为具有相应幺半群的扩充树。

    (这个概念让人联想到堆,或更明确的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)

使用递归函数,您可以通过使每个节点的值等于其子节点的值的总和,条件是它有两个子节点,或者它的单个子节点的值(如果它有一个子节点),并且如果它没有子(叶子),那么这就是破坏条件,值永远不会改变。