【问题标题】:Recursive function on stack堆栈上的递归函数
【发布时间】:2017-09-12 09:03:25
【问题描述】:

我有一个非常简单的函数来找出一堆整数的最大非负值。我想将此函数转换为递归函数。 有几点需要牢记:

  • 在运行函数之前,我们已经初始化了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;
        }
    } 
}

【问题讨论】:

  • 我不知道您为什么要将其转换为递归函数,因为您现在拥有的解决方案比递归函数更适合 C...
  • @AnttiHaapala 可能需要家庭作业?
  • @AnttiHappala:我正在努力更好地理解递归,并希望能够更流畅地从迭代函数到递归函数,反之亦然。就是这样。这个问题的目的是为了学习。我列举的限制是为了确保这两个函数是 100% 等效的。
  • “我们已经初始化了 num,但还没有给它赋值。” - 很难理解 的含义。如果它被初始化,它有一个确定的值。此外,num 在此代码中是一个指针,并且被取消引用,因此它更好 包含一个有效地址。如果您正在谈论取消引用的值,那么您当然可以通过*num = 0; 分配给它最后,您的迭代函数都找到最大值 并且 清空堆栈。那是故意的?你说这是最终结果,但在这里澄清一下。
  • @WhosCraig 我的意思是在调用函数之前我们只有这个:int number; /*我们还设置了一个整数栈“example_stack”,它可能是满的也可能是空的*/ /*我们现在调用函数*/ max_stack(&example_stack, &number); /*我们现在应该让example_stack为空,堆栈中的最大正值存储在number中*/

标签: c recursion stack iteration


【解决方案1】:

这将起作用的方式是,如果堆栈不为空,那么它将继续调用自己,并向前传递最大值。一旦堆栈为空,函数将通过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);

【讨论】:

  • @Josep 我还修复了以前版本的一个错误
  • 非常感谢您的回复。但请注意,该函数并非 100% 等效于我发布的迭代函数。关键是“void”函数应该对num的初始值不敏感:在调用函数之前我们能做的就是int num;
  • @Josep 很好,因为 num 是一个指针,如果我将原型更改为 void,它仍然可以工作
【解决方案2】:

为了匹配完全提供的迭代代码,我们还必须匹配这样的假设,即使在空堆栈上,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;
}

所以我们需要在当前帧中保存当前堆栈顶部,然后将其从堆栈中弹出(记住,我们将其保存在局部变量中):

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

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

recursive_max_stack(s, num);

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

if (lhs > *num)
    *num = lhs;

这会在我们展开调用时继续调用堆栈,最后返回到初始调用,然后返回调用者,*num 现在保存堆栈中最大的非负值,或者如果所有值都为 0负数(或堆栈为空)。

就是这样。这不关心 *num 中存储的原始值。它最终在达到最大递归深度时被0 替换,然后当随后的帧的lhs 值大于*num 中当前存储的值时,再次替换它

【讨论】:

  • 很好的解释。我唯一的疑问是为什么我们在*num=0之后需要return;
  • @Peter 将所有过去放在else 块中会使返回没有意义。这只是一种风格选择。无论哪种方式,您都可以这样做,但您不应该只删除return; 并保留代码原样。它不会起作用。
猜你喜欢
  • 2023-03-27
  • 2017-10-20
  • 2018-09-24
  • 2020-08-27
  • 2014-01-17
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
相关资源
最近更新 更多