【问题标题】:Assigning a depth to each node为每个节点分配深度
【发布时间】:2011-04-25 04:09:53
【问题描述】:

我在这里阅读了其他几篇看起来相似的文章,但并没有完全回答我的问题。我收到了一个问题,要求为二叉树中的每个节点分配其各自的深度。我就是不明白。

这是我的代码供参考:

struct treeNode {
   int item;
   int depth;
   treeNode *left;
   treeNode *right;
};
typedef treeNode *Tree;

int assignDepth(Tree &T, int depth)
{
    if(T!=NULL)
    {
        depth = assignDepth(T->left, depth++);
        T->depth = depth;
        depth = assignDepth(T->right, depth++);
    }
    else //leaf
        return depth--;
}

我试着用笔和纸把它看完了,看起来还不错,但我的办公桌检查技能显然不够。

谁能指出我正确的方向,好吗?这是我第一次使用树,递归不是我的强项。

答案:

void treecoords(Tree &T, int depth)
{
    static int count = -1; //set to -1 so the precrement before assignment doesn't give the wrong values
    if(T!=NULL)
    {
        treecoords(T->left, depth+1); //depth decrements automatically once this function call is removed from the stack
        count++;
        T->x = count;
          T->y = depth;
        treecoords(T->right, depth+1);
    } 
}

【问题讨论】:

  • 感谢所有回复我帖子的人。我明白我现在想的都是错的。我会离开并尝试根据您告诉我的内容修复代码并发布我的最终结果。我不想在没有完全理解的情况下使用某人的代码(尽管我很感激你为我发布了它,谢谢)。
  • 有效!我做了一个递归算法,最终匹配了库珀先生的算法。它实际上是更大算法的一部分,该算法将 x 和 y 坐标分配给树节点。该算法现在在原始问题中。

标签: c++ recursion binary-tree


【解决方案1】:

我有一个稍微复杂一点的设计,具有不同的节点类型,并且这样做了,所以我认为是 id share。

如果您有一棵节点类型不同的树(二进制、一元等),则值得简化传统方法以避免使用讨厌的嵌入式 IF 来检查节点类型。

两个功能:

  • 1:从根开始,遍历每个节点并检查其到节点的距离 root 通过递归调用自身并为每个父级加 1。给 每个节点都有一个深度变量来存储它。
  • 2:从树中的完整节点集运行 MAX 检查 针对每个节点深度,最大的数字将等于深度 树。

以这种方式处理消除了显式类型检查,并简单地计算节点,无论它有一个、两个还是一百个子节点。

希望这对某人有所帮助!

【讨论】:

    【解决方案2】:
    int assignDepth(Tree &T, int depth)
    

    您已将Tree 定义为指向treeNode 的指针。您不需要通过引用传递它。无论如何,您都可以修改指向的节点。

    {
        if(T!=NULL)
        {
            depth = assignDepth(T->left, depth++);
    

    后缀++ 可确保您将原始depth 向下传递。那不是你想要的。在此之前增加depth,忘记将其作为函数结果返回。

        T->depth = depth;
    

    没关系。

            depth = assignDepth(T->right, depth++);
    

    与前面的递归调用类似,只是这里你根本不应该修改depth,因为它已经增加了。

        }
      else //leaf
            return depth--;
    

    您不需要返回任何深度信息(或者这是未说明的要求?)。

    }
    

    干杯,

    【讨论】:

    • 我阅读了所有的 cmets 以确保我不会错过任何内容。谢谢:)
    【解决方案3】:
    1. 为什么当节点为 NULL 时返回。根据您的规范,您不需要返回任何深度
    2. 在其他情况下,您只需要增加深度并发送到函数调用。以下是我的代码版本

      void assignDepth(树 &T,int 深度) { 如果(T == NULL) 返回; 别的 { T->深度=深度; if(T->left != NULL) assignDepth(T->left,depth+1); if(T->right != NULL) assignDepth(T->right,depth+1); } }

    【讨论】:

    • 它开始变得更有意义了。我现在意识到,当递归完成时,它不需要返回深度,因为当它从堆栈中拉出函数调用时,深度与调用函数之前的值相同。谢谢:D!
    【解决方案4】:

    你不需要

    else //leaf
        return depth--;
    

    您也不想增加深度变量,只需将 depth+1 传递给下一个交互。

    也不需要返回值。

    试试这个:

    void assignDepth(Tree T, int depth)
    {
        if(T!=NULL)
        {
            assignDepth(T->left, depth+1);
            T->depth = depth;
            assignDepth(T->right, depth+1);
        }
    }
    

    【讨论】:

    • 我不明白为什么不这样做,但是每个人都说要删除它,所以我做了。递归打破了我的想法。谢谢:)
    • 它有助于思考正在发生的事情。在第一次调用中,depth = 0(或其他)并且 T 是树的根。假设 T 不为 NULL,该函数在左侧子树上调用自己,深度 +1,将深度分配给当前(根)节点,然后在右侧子树上调用自己,再次深度 +1。就是将depth参数的值赋给节点的中间步骤,所以不需要将值返回到任何地方。
    • 这是有道理的。我对递归返回的值有点困惑。但我想我现在明白了。非常感谢:)
    【解决方案5】:
    1. 一旦到达叶节点,就不再关心它的深度,因此返回值似乎什么也没做。

    2. 在两个语句中:

      depth = assignDepth(T->left, depth++);
      // and
      depth = assignDepth(T->right, depth++);
      

    在没有中间序列点的情况下修改depth 两次,你有未定义的行为(虽然看起来应该有,但在赋值的左右两侧之间没有没有序列点) .

    【讨论】:

    • 我刚刚意识到为什么在我输入这个时返回值是多余的。伙计,我觉得自己很愚蠢。谢谢 :)!不知道什么是序列点,抱歉。
    • @user475234:我什至对提及它进行了辩论,因为否则修复代码也会消除此问题。除了少数例外,C 基本上说您只能在给定语句中修改特定变量一次,在这种情况下,您将执行两次(一次在增量中,一次在赋值中)。
    【解决方案6】:

    嗯,对于初学者来说,您使用的是后增量/减量,您可能是指 ++depth/--depth 用于正确分配,否则返回;

    另外,为什么将指针作为引用变量传递?

    【讨论】:

    • 我按照您的建议尝试了这种方法,它已经到了那里,但不太正确。为什么我要使用 precrement 而不是 post?我认为这仅与操作顺序有关吗?我正在使用对指针的引用,因为它似乎是这样工作的。我们对指针进行了非常简短的介绍,然后掉进了树的海洋。这在很大程度上是一种猜测,并检查编译器何时停止向我抛出错误。
    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多