【问题标题】:Question on Tree data structure, print each level sum ( level sum = sum of siblings data )?关于树数据结构的问题,打印每个级别的总和(级别总和 = 兄弟数据的总和)?
【发布时间】:2025-12-24 22:35:11
【问题描述】:

下面我写了一段代码来回答这个问题。你请告诉我 1) 如果您在我的代码中发现任何缺陷 2) 任何其他最佳解决方案

问题: 关于Tree数据结构的问题,打印每一层总和(层总和=兄弟数据总和)?

struct tree{
             int data;
             struct *left;
             struct *right;
 };

API 原型是 void EachLevelSum(struct tree *root);

我的答案是

void EachLevelSum(struct tree *root )
{
     static int level=0;
     static int a[100] = {0}; // I am assuming , at MAX 100 levels in tree

     if( root == NULL )
     {
           return;
     }
     else
     {
           a[level += root->data;

           level++;
           EachLevelSum(root->left);
           level--;      

           level++;
           EachLevelSum(root->right);
           level--;      

           if( level == 0 )
           {
               int i;
               for( i=0; i<100 && a[i]!=0 ; i++)
               {
                   printf("\n level: %d sum = %d", i,  a[i] );
               }

           }
     }

}

【问题讨论】:

  • EachLevelSum 中的第 12 行有一个错字 a[level += 需要是 a[level] +=
  • 你有没有想过定义一个增广树,即每个节点都会存储这个级别的总和,并且每当树更新时它都会更新。然后查询它只是查看根和的简单问题:)

标签: c algorithm recursion tree


【解决方案1】:

我觉得还不错!不过,我可以说一两件事,这可能会帮助您改进它。

1 -- 静态变量的使用。这不是被禁止的,但你应该避免这种情况。现在,您会如何看待您的解决方案本质上是递归的,并且您需要在调用之间共享数据?

一般的方法是使用第二个函数,它包装递归调用,并向它传递额外的参数。在你的情况下:

void eachLevelSum(struct tree*);
static void eachLevelSumRecursive(struct tree*, int level, int* results);

然后,类似:

void eachLevelSum(struct tree* t) {
    int results[100];
    eachLevelSumRecursive(t, 0, results);

    return;
}

然后在您的递归函数中,每当您进入递归时,您都可以将 level 参数作为 level + 1 传递,而不是像这样执行 level++ 和 level-- =D:

eachLevelSumRecursive(t->left, level + 1, results);
eachLevelSumRecursive(t->right, level + 1, results);

请注意,这不仅更清洁,而且还有其他优点。例如,这种方法可以在多线程环境中使用,而另一种则不能,因为它依赖于静态变量。

2 -- 您可能希望使用 typedef 和改变结构的函数进一步封装您的树。如果您想了解更多信息,请询问。不过,这对你的锻炼来说完全没有必要。

3 -- 记住函数名通常以小写字母开头。

这就是我要说的一切,您的代码非常干净!恭喜!

【讨论】:

  • 3) 实际上是您编写代码的地方的命名约定问题。我见过相反的代码库。
【解决方案2】:

您的代码似乎正确。用英语你的逻辑状态 -

对于您下降到树中的每个级别(左侧和右侧),跟踪您的深度并将data 添加到全局总和跟踪变量a

除非你对你的结构做出重大改变——这是唯一的方法(我能想到的)

【讨论】:

    【解决方案3】:

    我会避免使用 level 作为全局变量。在这种特殊情况下,这并不重要,因为没有线程或类似的复杂性。但最好养成避免使用全局变量的习惯。

    总是首选使用局部变量而不是全局变量,除非您必须使用全局变量并且需要小心。

    我会在方法中添加 level 作为参数,而不是 level++ 和 level--,我只是将 level+1 传递给方法调用。

    【讨论】:

      【解决方案4】:

      我认为您的代码很好。

      您也可以使用 BFS 搜索:http://en.wikipedia.org/wiki/Breadth-first_search。这是示例 C# 代码

          class Tree
          {
              public int data;
              public Tree Left;
              public Tree Right;
      
      
                  static int[] levels = new int[100];
      
                  static void EachLevelSum(Tree root)
                  {
                      // keeps track of each tree node's level
                      Dictionary<Tree, int> treeLevels = new Dictionary<Tree,int>();
                      treeLevels.Add(root, 0);
      
                      // Do a BFS search and update the level of each node
                      Queue<Tree> trees = new Queue<Tree>();
                      trees.Enqueue(root);
      
                      while (trees.Count != 0)
                      {
                          Tree node = trees.Dequeue();
                          int level = treeLevels[node];
                          if (node.Left != null)
                          {
                              treeLevels.Add(node.Left, level + 1);
                              trees.Enqueue(node.Left);
                          }
                          if (node.Right != null)
                          {
                              treeLevels.Add(node.Right, level + 1);
                              trees.Enqueue(node.Right);
                          }
                      }
                      foreach (Tree node in treeLevels.Keys)
                      {
                          int level = treeLevels[node];
                          levels[level] += node.data;
                      }
      
                  }
          }
      

      【讨论】: