C 堆栈上的递归函数

C 堆栈上的递归函数,c,recursion,stack,iteration,C,Recursion,Stack,Iteration,我有一个非常简单的函数来计算一堆整数的最大值,非负值。我想把这个函数转换成递归函数。 有几点需要记住: 在运行函数之前,我们已经初始化了num,但没有为其分配任何值。请注意,我们不应该依赖这样一个事实:在某些条件下,C会自动将0分配给num 运行函数后,堆栈s为空,我们将最大非负值存储在num 我是C和数据结构的初学者,所以请友好:) 这是迭代函数: void max_stack(stack *s, int *num){ *num = 0; int aux = 0;

我有一个非常简单的函数来计算一堆整数的最大值,非负值。我想把这个函数转换成递归函数。 有几点需要记住:

  • 在运行函数之前,我们已经初始化了
    num
    ,但没有为其分配任何值。请注意,我们不应该依赖这样一个事实:在某些条件下,C会自动将0分配给
    num
  • 运行函数后,堆栈
    s
    为空,我们将最大非负值存储在
    num
  • 我是C和数据结构的初学者,所以请友好:)
这是迭代函数:

void max_stack(stack *s, int *num){
    *num = 0;
    int aux = 0;
    while (!emptyStack(*s)){
        aux = top(*s);
        pop(s);
        if (aux>*num){
            *num = aux;
        }
    } 
}

这样做的方式是,如果堆栈不是空的,那么它将继续调用自身,并向前传递最大值。堆栈为空后,函数将通过num指针逐个返回最大值

此处为伪代码:

void max_stack(stack *s, int * num){
    int aux = 0;
    if(!emptyStack(*s)){
        aux = top(*s);
        pop(s);
        if (aux > (*num)){
            (*num) = aux;
        }
        max_stack(s, num);
    }
}
第一次调用此函数时,您可以这样调用它:

int num = 0
max_stack(s, &num);
为了精确匹配所提供的迭代代码,我们还必须匹配这样的假设,即即使在空堆栈上,
0
是将存储在目标参数中的最小值

因此:

void recursive_max_stack(stack *s, int *num)
{
    if (emptyStack(*s))
    {
        *num = 0;
        return;
    }

    int lhs = top(*s);
    pop(s);

    recursive_max_stack(s, num);

    if (lhs > *num)
        *num = lhs;
}
解释

首先,我们需要一个默认情况(当堆栈中没有元素时)。与迭代函数一样,默认情况下存储零

if (emptyStack(*s))
{
    *num = 0;
    return;
}
因此,我们需要在当前帧中保存当前堆栈顶部,然后将其从堆栈中弹出(请记住,我们将其保存在局部变量中):

一旦完成,我们就可以递归

recursive_max_stack(s, num);
从递归返回时,将每个
lhs
*num
的内容进行比较(当我们达到最大深度时,它被设置为
0
)。如果更大,
lhs
将替换存储在
*num
中的值

if (lhs > *num)
    *num = lhs;
这将在我们展开调用时继续向上调用堆栈,最后返回到初始调用,然后返回到调用方,
*num
现在保留堆栈中最大的非负值,或者如果所有值都为负值(或堆栈为空),则为零


就这样。这与存储在
*num
中的原始值无关。在达到最大递归深度时,它最终被替换为
0
,然后在后续帧的
lhs
值大于
*num

中当前存储的值时再次替换,我不知道为什么要将其转换为递归函数,当您现在的解决方案比递归函数更适合C时,…@AnttiHaapala作业要求可能?@AnttiHappala:我试图更好地理解递归,并且希望更流畅地从迭代函数到递归函数,反之亦然。就这样。这个问题的目的是为了学习。我列举的限制是为了确保这两个函数100%等效。“我们已经初始化了num,但没有给它赋值。”-很难巩固这意味着什么。如果它已初始化,则具有确定的值。另外,
num
是此代码中的指针,并且被取消引用,因此它最好包含一个有效地址。如果您谈论的是取消引用的值,那么您肯定会通过
*num=0为其赋值最后,迭代函数会找到最大值并清空堆栈。那是故意的?您说过这是最终结果,但只是在这里澄清一下。@whoscratig我的意思是,在调用函数之前,我们只有以下内容:int number/*我们还设置了一个整数堆栈“example_stack”,它可以是满的或空的*/*我们现在调用函数*/max_stack(&example_stack,&number)/*我们现在应该让示例_堆栈为空,堆栈中存储在number*/@Josep I中的最大正值也修复了前一版本中的一个bug,感谢您的响应。但是请注意,该函数并不是100%等价于我发布的迭代函数。关键的一点是“void”函数应该对num的初始值不敏感:在调用函数之前,我们所能做的就是
intnum@Josep很好,因为num是一个指针,如果我将原型更改为优秀的解释,它应该仍然有效。我唯一的疑问是为什么我们需要
返回*num=0
@Peter之后,将所有内容放在
else
块中,将使返回无效。这只是一种风格选择。您可以采用任何一种方式,但不应该只删除
返回并保持代码不变。这行不通。
if (lhs > *num)
    *num = lhs;