这是尾递归吗?

时间:2011-02-19 08:46:05

标签: tail-recursion

我写了一个函数来计算整数的幂,然后取模数。我想知道我做的是尾递归:

int takeModulusTAILRECURSION(int coef, int x, int n, int module){
        int result = 0;
        if ( n > 0 )
            result = takeModulusTAILRECURSION( mod(coef * x, module), x , n - 1, module  );
        else if ( n == 0)
            result = mod ( coef , module );
        return result;
    }

//take modul of an integer ( both negative and positive )
int mod(int x, int modul){
    while ( x < 0) 
        x += modul;
    return x % modul;
}

这是另一个纯粹使用递归的函数,我认为它与上面不同:

int takeModulusNORMRECURSION(int x, int n, int module){
    if ( n == 1 )
        return mod( x, module );
    else {
        int total = x * takeModulusNORMRECURSION( x, n - 1, module);
        return mod( total, module);
    }
}

顺便说一句,在这些情况下,任何人都可以告诉我如何检查Eclipse中的帧堆栈?当我尝试(不知道对错)时,他们都运行了很多堆栈。

3 个答案:

答案 0 :(得分:0)

这是否是尾递归取决于代码的编译方式。

当您直接将调用返回到另一个函数(可能是您自己)时,会发生尾递归。当编译器/解释器注意到这一点时,会发生尾调用优化(人们关心尾递归的原因),只是替换当前的堆栈帧而不是创建另一个堆栈帧。在你的情况下,如果它被天真地编译,你没有尾递归,因为你正在进行递归调用,然后将它分配给你的调用堆栈中的一个变量,稍后你将返回该变量。那个赋值步骤意味着你在调用另一个函数之后会做更多的事情,这会使你的代码不适合尾部调用优化。

然而一个好的编译器应该像这样重写你的代码:

int takeModulusTAILRECURSION(int coef, int x, int n, int module){
    if ( n > 0 )
        return takeModulusTAILRECURSION( mod(coef * x, module), x , n - 1, module  );
    else if ( n == 0)
        return mod ( coef , module );
    else
        return 0;
}

//take modul of an integer ( both negative and positive )
int mod(int x, int modul){
    while ( x < 0) 
        x += modul;
    return x % modul;
}

现在它是尾递归的。

但是现在是否可能发生尾调用优化取决于语言和实现。例如,如果你的代码应该是Java,那么正如Does the JVM prevent tail call optimizations?指出的那样,无论你做什么,你都不会得到尾调用优化。

编辑:我说“tail recursive”表示“尾递归和尾调优化”。

答案 1 :(得分:0)

第一种方法是尾递归,因为当函数执行'return'时,它返回的值是一个不依赖于当时对另一个方法的调用的值。

第二种方法不是尾递归,事实上它不是递归的,因为它只是迭代x的值的变化。

第三个也是最后一个方法也是尾递归的,因为像第一个例子一样,当方法“返回”时,它能够在不调用任何方法的情况下这样做,包括它自己。

希望这有帮助。

答案 2 :(得分:0)

  1. 是尾递归,直接返回尾递归调用的结果
  2. 不是递归的,因此甚至不是尾递归的
  3. 不是尾递归。不返回递归调用的结果,但会进一步处理结果。