嵌套递归调用 - 这是尾递归吗?

Posted

技术标签:

【中文标题】嵌套递归调用 - 这是尾递归吗?【英文标题】:Nested recursive calls - is this tail recursion? 【发布时间】:2020-05-03 15:11:23 【问题描述】:

我想我理解了尾递归函数的教科书定义:函数调用后不执行任何计算的函数。我也明白,尾递归函数的内存效率会更高,因为每次调用它只需要一条记录,而不是每次都需要保留一条记录(就像在正常递归中一样)。

我不太清楚的是这个定义如何应用于嵌套调用。我举个例子:

func foo91(x int)
    if(x > 100):
        return x - 10
    else:
        return foo91(foo91(x+11))

我最初想出的答案是它不是尾递归定义(因为外部调用是在评估内部调用之后执行的,所以其他计算是在第一次调用之后完成),因此通常具有嵌套递归调用的函数不是尾递归的;另一方面,它在实践中是相同的,因为它具有尾递归函数的副作用:在我看来,整个函数需要单个激活记录。这是真的吗?

嵌套递归函数调用通常是相当大的尾递归吗?

【问题讨论】:

正如您所确定的,只有一个递归调用可以通过尾递归进行优化,另一个不能。因此,如果问题是“此函数是否进行任何尾递归调用?”答案是肯定的,但如果是“这个函数是否只进行尾递归调用?”答案是否定的。 【参考方案1】:

你的理解只是部分正确。

您正确定义了尾递归。但它是否真的有效取决于实现。在像 Scheme 这样的一些语言中是这样。但是大多数语言都像 javascript,但事实并非如此。特别是关键的权衡之一是使尾递归有效意味着您会丢失堆栈回溯。

现在对于您的实际问题,内部调用不是尾递归,因为它必须回到您的调用并执行其他操作。但是外部调用是尾递归的。

【讨论】:

以上是关于嵌套递归调用 - 这是尾递归吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使涉及期货尾递归的函数?

递归和尾递归

JavaScript函数尾调用与尾递归

Python进阶 —— 尾递归

七 递归与二分法匿名函数内置函数

尾递归