【问题标题】:Binary tree where value of each node holds the sum of child nodes二叉树,其中每个节点的值包含子节点的总和
【发布时间】:2011-03-20 17:49:20
【问题描述】:

这个问题是在一次采访中问我的。我们如何转换一个 BT 使得其中的每个节点都有一个值是它的子节点的总和?

【问题讨论】:

  • 好吧,如果他们只能存储子节点的总和,他们都只会存储值 0。最终,树的叶子没有子节点,所以它们的总和为 0,因此向上通过树全为零。 :)

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


【解决方案1】:

给每个节点一个附加值。当你构造树时,叶子的值就设置好了;构造内部节点以具有值leaf1.value + leaf2.value

如果您可以更改叶节点的值,则操作必须“备份”树更新总和值。

如果您在节点中包含反向链接,或者将树实现为“threaded tree”,这将容易得多。

【讨论】:

    【解决方案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查看完整的解决方案和解释!

    【讨论】:

      【解决方案3】:

      正如查理指出的那样,您可以简单地将各个子树大小的总和存储在每个内部节点中,并让叶子在构造时提供常量值(或者如果您只对叶子的数量感兴趣,则始终隐式使用 1在树上)。

      这通常称为增强搜索树。

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

      1. 数据类型 M;在你的例子中,整数
      2. 一个二元运算“op”来组合元素,用M op M -> M;在您的示例中,常见的“加号”运算符

      所以除了子树大小之外,您还可以表达如下内容:

      • 优先级(通过“min”或“max”运算符),用于高效查询最小/最大优先级;
      • 子树中最右边的元素(即,简单地返回其第二个参数的“op”运算符),前提是您存储在树中的元素以某种方式排序。请注意,这使我们甚至可以将常规搜索树(又名字典——“存储这个,检索那个键”)视为具有相应幺半群的增强树。

      (这个概念很容易让人联想到堆,或者更明确地说是堆,它使用内部节点存储随机优先级以实现概率平衡。它在手指树的上下文中也很常见,尽管它们不是一回事。)

      如果你还为你的幺半群提供了一个中性元素,那么你可以沿着这样一个幺半群增强的搜索树来检索特定元素(例如,“为你的大小示例找到第 5 片叶子”;“给我叶子具有最高优先级”)。

      嗯,无论如何。那里可能有点忘乎所以。我只是碰巧发现这个话题很有趣。 :)

      【讨论】:

      • 这是一个很好的概括,我喜欢它。
      【解决方案4】:

      这是求和问题的代码。它的工作原理我已经测试过。

      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;
      
      
      }
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-18
          • 2015-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多