【问题标题】:Find what Level an Element is in Tree查找元素在树中的级别
【发布时间】:2020-12-09 02:58:16
【问题描述】:

所以我遇到了这个问题,我应该在树中找到元素的级别。似乎什么都没有解决,所以我在这里寻求帮助。

这是我到目前为止所得到的。这里的问题是第 4 个断言(返回的级别应该是 2)不起作用并且断言被警告。我曾想过也许尝试不递归地执行此操作,但怎么能这样做呢?

int findElementLevel(const BSTree tree, const int element) {

    int level = 0;

    if (tree == NULL) {
        return -1;
    }

    if (tree->data == element) {
        return level;
    }

    if (element < (tree)->data) {
        level++;
        findElementLevel(tree->left, element);
        return level;
    }

    if (element > (tree)->data) {
        level++;
        findElementLevel(tree->right, element);
        return level;
    }
}

void testNewTree(void) {

    BSTree tree = emptyTree();
    assert(isEmpty(tree));

    int arr[5] = {3,2,5,1,4}, i;

    for (i = 0; i < 5; i++)
    {
        insertSorted(&tree, arr[i]);
    }

    assert(findElementLevel(tree, 3) == 0);

    assert(findElementLevel(tree, 2) == 1);

    assert(findElementLevel(tree, 5) == 1);

    assert(findElementLevel(tree, 1) == 2);

    assert(findElementLevel(tree, 4) == 2);

}

【问题讨论】:

  • level 是一个局部变量。顶级函数返回时,它始终为 0 或 1。
  • 您在每次递归中重置局部变量level。也许它应该是 static int level = 0; 然后你还需要在返回时递减(这样下次就可以了)。
  • 级别应该从 0 开始,但在函数返回时不会重置。但我不知道如何解决它。级别不允许是静态变量或全局变量
  • 为什么不允许?
  • 可以是函数的参数。

标签: c recursion tree binary-search-tree function-definition


【解决方案1】:

函数总是从设置为0的局部变量level的声明开始。

int findElementLevel(const BSTree tree, const int element) {

    int level = 0;

如果在任何实际级别中找到目标元素,则返回此值为 0(或由于在当前递归函数调用中递增而为 1)的值

if (tree->data == element) {
    return level;
}

你必须积累等级。

递归函数可以定义为例如以下方式

int findElementLevel(const BSTree tree, const int element) {
    if (tree == NULL) {
        return -1;
    }
    else  if ( element < tree->data ) {
        int level = findElementLevel(tree->left, element);
        return level == -1 ? level : level + 1;
    }
    else if ( tree->data < element ) {
        int level = findElementLevel(tree->right, element);
        return level == -1 ? level : level + 1;
    }
    else {
        return 0;
    } 
}

请注意,第二个参数的限定符 const 没有多大意义,因为该函数处理所提供参数值的副本。函数可以像这样声明

int findElementLevel(const BSTree tree, int element);

【讨论】:

  • 我应该返回元素在树中的哪个级别。我也不明白这里发生了什么“?级别:++级别;”
  • @JohnJohn:如果你将return level == -1 ? level : ++level; 替换为return level &lt; 0 ? -1 : level+1;,它会做同样的事情,你可能会更好地理解它。表达式a ? b : c 测试a,如果a 为真,则使用b,如果a 为假,则使用c。 (这个三元运算符? :也可以用来选择树分支来探索和消除冗余代码;我们不需要单独的子句和左右两边的调用。)
  • @JohnJohn 如果下一个递归调用返回 -1(这意味着未找到该元素),那么它会进一步返回。否则,如果在下一次调用中找到它,则递增返回。
  • @JohnJohn 实际上这个构造返回级别 == -1 ?级别:++级别;相当于 if ( level == -1 ) 返回级别;否则返回++级;
  • 好吧,我想现在一切都解决了。只是需要在发送之前进行更多测试,感谢所有帮助。如果出现更多问题,我们会与您联系。
【解决方案2】:

此函数以迭代方式编写比递归编写更容易且更短。代码只是:

int findElementLevel(const BSTree tree, const int element)
{
    for (int level = 0; tree; ++level)
    {
        if (tree->data == element)
            return level;
        tree = tree->data < element ? tree->left : tree->right;
    }
    return -1;
}

加上解释,就是:

int findElementLevel(const BSTree tree, const int element)
{
    /*  Use a loop to process each level.  We start counting levels at zero and
        increment on each iteration.  We continue as long as there is more of
        the tree to explore ("tree" evaluates as true, i.e., non-null), or jump
        out of the loop with a return if the target element is found.
    */
    for (int level = 0; tree; ++level)
    {
        //  If we found the target, return the level it is on.
        if (tree->data == element)
            return level;

        /*  Otherwise, descend to the left or the right according to which
            side the target element must be on.
        */
        tree = tree->data < element ? tree->left : tree->right;
    }

    /*  If we reached the end of the tree without finding the element, return
        -1.
    */
    return -1;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    相关资源
    最近更新 更多