简体   繁体   English

这是尾递归吗?

[英]Is this tail recursion?

I have tried to find examples of tail recursion and I really don't see the difference between regular and tail. 我试图找到尾递归的例子,我真的没有看到常规和尾部之间的区别。 If this isn't tail recursion, can someone tell me why its not? 如果这不是尾递归,有人可以告诉我为什么不是?

public static long fib(long index) {

// assume index >= 0

if (index == 0) // Base case

  return 0;

else

  if (index == 1) // Base case

    return 1;

  else

    // Reduction and recursive calls

    return fib(index - 1) + fib(index - 2);

}  // end of method fib(long index)

No, the method in the question does not use a tail recursion. 不,问题中的方法不使用尾递归。 A tail recursion is easily recognizable: the recursive step is the last thing that happens in the method. 尾递归很容易识别:递归步​​骤是方法中发生的最后一件事。

In your code, after both recursive calls end, there's one more operation to do - an addition. 在你的代码中, 两个递归调用结束之后,还有一个操作要做 - 一个加法。 So the method is recursive , but not tail-recursive . 所以该方法是递归的 ,但不是尾递归的

For comparison purposes, here's a tail-recursive implementation of the fib() method - notice how we need to pass extra parameters to save the state of the recursion, and more importantly, notice that there are no operations left to do after the recursive call returns. 为了进行比较,这里是fib()方法的尾递归实现 - 注意我们需要传递额外的参数来保存递归的状态,更重要的是,请注意在递归调用之后没有剩下的操作要做回报。

public static long fib(int n, long a, long b) {
    return n == 0 ? b : fib(n-1, a+b, a);
}

Use it like this: 像这样使用它:

fib(10, 1, 0) // calculates the fibonacci of n=10
=> 55

The previous implementation will work fine up to n=92, for bigger numbers you'll have to use BigInteger instead of long , and better switch to an iterative algorithm. 之前的实现将在n = 92时正常工作,对于更大的数字,您将不得不使用BigInteger而不是long ,并且更好地切换到迭代算法。

@Óscar López has answered the Question. @ÓscarLópez回答了这个问题。

The reason that people are interested in knowing whether a call is tail call is that there is an optimization that allows a tail call to be replaced with a branch, thereby avoiding the need to create a new stack frame. 人们有兴趣知道调用是否是尾调用的原因是有一个优化允许尾部调用被分支替换,从而避免了创建新堆栈帧的需要。 This allows unbounded tail recursion on a bounded stack. 这允许在有界堆栈上进行无界尾递归。

However, since you tagged the Question with java , you should know that current Java implementations DO NOT implement tail call optimization. 但是,由于您使用java标记了Question,您应该知道当前的Java实现不实现尾调用优化。 A deeply recursive method call in Java is liable to result in a StackOverflowError . Java中的深度递归方法调用容易导致StackOverflowError

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM