是不是使用与递归相同的堆栈?

时间:2014-07-12 08:55:17

标签: recursion stack

当被要求使用非递归算法来解决问题时,人们经常使用堆栈,但实质上不是堆栈和递归相同吗?此外,当堆栈用于替换递归时,空间复杂度保持不变(渐近)。我没有遇到任何根本的区别 观察?

3 个答案:

答案 0 :(得分:1)

您的应用程序堆栈大小比数据结构堆栈更受限制。只要您可以动态分配内存(实际上这次它依赖于应用程序 heap ),您就没有问题。

您提到的应用程序堆栈更加有限,并且它具有每个临时局部变量,函数参数,返回值,堆栈指针和ext的副本。这使它的尺寸比看起来更小。

答案 1 :(得分:0)

在某些情况下,Big-O复杂度可能相同,但使用显式堆栈的常数因素通常更好。此外,机器执行堆栈的大小通常相对较小,而显式(堆分配)堆栈可能会变得更大。

有时你会想要寻找一种完全不同的算法,这种算法恰好是非递归的,它会表现得更好。考虑一下天真的斐波纳契序列算法:

int f(int n)
{
    if (n < 2)
    {
         return 1;
    }

    return f(n-2) + f(n-1);
}

此算法采用指数时间:(

非递归版本(在这种情况下实际上是一种“动态编程”)在n中只是线性的,并且不使用堆栈:

int f(int n)
{
    int fMinusOne = 1;
    int fMinusTwo = 1;
    for (int idx = 1; idx < n; ++idx)
    {
        int next = fMinusOne + fMinusTwo;
        fMinusTwo = fMinusOne;
        fMinusOne = next;
    }

    return fMinusOne;
}

答案 2 :(得分:0)

是的,它完全是一样的。

使用堆栈而不是使用调用堆栈是一种解决方法(当一种语言的堆栈空间少于程序需要处理的最大值时),或者它是一种优化,可以节省一些空间,因为堆栈帧通常用一些没有TCO的语言来获取一些机器字,或者你不需要以相同的方式存储数据,因此即使每个项目的堆栈空间效率较低,它也会使总消耗量大大减少。 / p>

并非所有语言都需要它,在Racket语言中,它不能用于任何目的使用显式堆栈,因为堆栈没有限制,因为除了总计内存以外,即使非TCO也是如此调用(如树遍历)它仍然可以工作,直到所有内存都被消耗。

在Java中,启动程序时可以配置堆栈空间。它更喜欢读取递归代码,因此在恢复使用显式堆栈之前,请检查您的语言是否可以执行此操作。