嵌套递归调用——这是尾递归吗?
Nested recursive calls - is this tail recursion?
我想我理解教科书上对尾递归函数的定义:在函数调用后不执行任何计算的函数。我也明白,尾递归函数的内存效率会更高,因为它每次调用只需要一个记录,而不需要每次都保留一条记录(就像在正常递归中一样)。
我不太清楚这个定义如何应用于嵌套调用。我举个例子:
func foo91(x int)
if(x > 100):
return x - 10
else:
return foo91(foo91(x+11))
我最初想出的答案是它不是尾递归根据定义(因为外部调用是在之后评估内部的,所以其他计算在第一次调用之后完成),所以通常具有嵌套递归调用的函数不是尾递归的;另一方面,它在实践中是相同的,因为它具有尾递归函数的副作用:在我看来,整个函数需要一个激活记录。是真的吗?
嵌套递归函数调用一般都是相当大的尾递归吗?
您的理解只对了一部分。
您正确定义了尾递归。但它是否真的有效取决于实现。在某些语言中,例如 Scheme,它是。但是大多数语言都像 JavaScript 而不是。特别是关键的权衡之一是使尾递归有效意味着你失去堆栈回溯。
现在回答您的实际问题,内部调用不是尾递归的,因为它必须返回到您的调用并执行其他操作。但是外部调用是尾递归的。
我想我理解教科书上对尾递归函数的定义:在函数调用后不执行任何计算的函数。我也明白,尾递归函数的内存效率会更高,因为它每次调用只需要一个记录,而不需要每次都保留一条记录(就像在正常递归中一样)。
我不太清楚这个定义如何应用于嵌套调用。我举个例子:
func foo91(x int)
if(x > 100):
return x - 10
else:
return foo91(foo91(x+11))
我最初想出的答案是它不是尾递归根据定义(因为外部调用是在之后评估内部的,所以其他计算在第一次调用之后完成),所以通常具有嵌套递归调用的函数不是尾递归的;另一方面,它在实践中是相同的,因为它具有尾递归函数的副作用:在我看来,整个函数需要一个激活记录。是真的吗?
嵌套递归函数调用一般都是相当大的尾递归吗?
您的理解只对了一部分。
您正确定义了尾递归。但它是否真的有效取决于实现。在某些语言中,例如 Scheme,它是。但是大多数语言都像 JavaScript 而不是。特别是关键的权衡之一是使尾递归有效意味着你失去堆栈回溯。
现在回答您的实际问题,内部调用不是尾递归的,因为它必须返回到您的调用并执行其他操作。但是外部调用是尾递归的。