【问题标题】:Recursion, Tail Recursion and Iteration递归、尾递归和迭代
【发布时间】:2011-11-14 06:08:18
【问题描述】:

这是我的代码。

递归:

#include <stdio.h>

int Recursion(int m,int n)
{
    if(m==0 || n==0)
        return 1;
    else
        return 2*Recursion(m-1,n+1);
}

void main()
{
    int m,n,result;
    m=3;
    n=-2;
    result=Recursion(m, n);
    printf("%d",result);
}

迭代

#include <stdio.h>

int Recursion(int m,int n)
{
    int returnvalue=1;
    while(m!=0 && n!=0)
    {
        returnvalue=returnvalue*2;
        m--; n++;
    }
    return returnvalue;
}

void main()
{
    int m,n,result;
    m=3;
    n=-2;
    result=Recursion(m,n);
    printf("%d",result);
}

现在我的疑问是:

  1. 我读到要从递归更改为迭代,您需要使用堆栈并继续推送数据并稍后弹出。现在我看不到在这里做。为什么?什么时候使用堆栈,什么时候不使用?
  2. 我对迭代版本的翻译在这里正确吗?这个尾递归是不是因为Recursion 代码的来源是这样说的。
  3. 如何从递归版本更改为迭代版本。我真的需要一个很好的资源来研究这个。谷歌搜索没有多大帮助。

【问题讨论】:

  • 你的尾递归是错误的。尾递归函数调用只能发生在“之前”return (iow return tailcalled(foo);)。

标签: c recursion iteration tail-recursion


【解决方案1】:

1) 当每次调用都有要保存的值时,您需要使用堆栈。在您的情况下,您不会在递归调用之后使用来自更深层次的递归调用的值,因此没有任何东西可以保存在堆栈上。

2) 如果对自身的调用是它做的最后一件事,那么它就是尾递归。作为@leppie cmets,您在最后一次方法调用之后执行2*

3) 一般的做法是使用栈;但是,在这种情况下,堆栈中没有可保存的内容,因此您可以删除它。

这里有一些例子,一个需要堆栈,另一个使用尾递归但不需要。

void reverseCounting(int i, int n) {
    if (i >= n) return;
    reverseCounting(i + 1, n);
    cout << i << endl;
}

void counting(int i, int n) {
    if (i >= n) return;
    cout << i << endl;
    counting(i + 1, n);
}

// you could just count backwards, but this is a simple example.
void reverseCountingLoop(int i, int n) {
    // for C you can write you own stack to do the same thing.
    stack<int> stack; 
    //// if (i >= n) return;
    while (!(i >= n)) {
        //// reverseCounting(i + 1, n);
        // save i for later
        stack.push(i);
        // reuse i
        i = i + 1;
    }
    // unwind the stack.
    while (!stack.empty()) {
        //// cout << i << endl;
        i = stack.top(); stack.pop();
        cout << i << endl;
    }
}

void countingLoop(int i, int n) {
    //// if (i >= n) return;
    while (!(i >= n)) {
        //// cout << i << endl;
        cout << i << endl;
        //// counting(i + 1, n);
        // reuse i
        i = i + 1;
    }
    //// nothing after the recursive call.
}

【讨论】:

  • 所以我可以在我想从递归更改为迭代时使用堆栈,或者仅从尾递归更改?
  • 如果需要,您可以每次都创建一个堆栈,但只有在需要保存的时候才需要一个堆栈。对于尾递归,永远没有要保存的内容,因为在递归调用之后没有代码可以使用保存的值。
  • ok.. 所以对于尾递归,只能使用循环进行转换..!谢谢。
  • 我添加了一些示例,希望对您有所帮助。
【解决方案2】:

您应该知道尾递归比递归更优化。编译器知道这是一个递归,可能会改变一些东西。

【讨论】:

    猜你喜欢
    • 2016-06-14
    • 2016-05-09
    • 2016-04-07
    • 2012-10-05
    • 2012-10-17
    • 2019-12-10
    • 2016-03-21
    • 1970-01-01
    • 2017-11-11
    相关资源
    最近更新 更多