簡體   English   中英

二叉樹,其中每個節點的值包含子節點的總和

[英]Binary tree where value of each node holds the sum of child nodes

在接受采訪時我問過這個問題。 我們如何轉換BT以使其中的每個節點都具有一個值,該值是其子節點的總和?

為每個節點提供附加值。 構造樹時,設置葉子的值; 構造內部節點的值為leaf1.value + leaf2.value

如果您可以更改葉節點的值,則操作必須“備份”更新總和值的樹。

如果要么在節點中包含反向鏈接,要么將樹實現為“ 線程樹 ”,這將更容易。

這是一個可以幫助您的解決方案:(鏈接用樹形圖解釋)

將任意二進制樹轉換為包含Children Sum屬性的樹

/* 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);
  }
}

請參閱鏈接以查看完整的解決方案和說明!

正如Charlie指出的那樣,你可以簡單地在每個內部節點中存儲各個子樹大小的總和,並在構造時提供常量值(或者如果你只對樹中的葉子數感興趣,則總是隱式使用1) )。

這通常稱為增強搜索樹。

有趣的是,通過這種擴充,即存儲額外的每節點數據,您還可以為樹中的項目導出其他類型的聚合信息。 您可以表示為可以存儲在增強樹中的monoid的任何信息,為此,您需要指定:

  1. 數據類型M; 在你的例子中,整數
  2. 二元運算“op”組合元素,M op M - > M; 在您的示例中,常見的“加號”運算符

所以除了子樹大小,你還可以表達如下內容:

  • 優先級(通過“min”或“max”運算符),用於有效查詢最小/最大優先級;
  • 子樹中最右邊的元素(即,只是返回其第二個參數的“op”運算符),前提是存儲在樹中的元素以某種方式排序。 請注意,這允許我們甚至可以查看常規搜索樹(也稱為詞典 - “將此存儲,檢索該鍵”)作為具有相應幺半群的擴充樹。

(這個概念讓人聯想到堆,或更明確的treaps,它存儲隨機優先級與內部節點進行概率平衡。它也常見於Finger Trees的上下文中,盡管這些並不相同。)

如果你還為你的幺半群提供一個中性元素,那么你可以走下這樣一個幺半群增強的搜索樹來檢索特定的元素(例如,“找到我的第五片葉子”為你的大小例子;“給我最高的葉子優先”)。

嗯,反正。 可能會在那里被帶走......我碰巧發現這個話題非常有趣。 :)

這是總和問題的代碼。 它的工作原理我測試過它。

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;


}

使用遞歸函數,您可以通過使每個節點的值等於它的子節點的值的總和,條件是它有兩個子節點,或者它的單個子節點的值(如果它有一個子節點),如果它有沒有孩子(葉子),那么這是破壞條件,價值永遠不會改變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM