int gcd(int a,int b){
if(a == b) return a;
else if (a>b) return gcd(a-b,b);
else return gcd(a,b);
}
例如,我认为这是尾递归的,因为你没有调用另一个函数。
int gcd(int a,int b){
int x;
if(a == b) x=a;
else if (a>b) x= gcd(a-b,b);
else x= gcd(a,b);
return x;
}
这是非尾递归的,因为它调用函数gcd。
我是对的吗?或者有没有更简单的方法来区分尾/非尾递归调用?
答案 0 :(得分:2)
首先,出于g ++ TCO(尾部调用优化)的目的,无论是进行递归调用还是完全调用其他函数都无关紧要 - 函数调用将被无条件跳转替换。
其次,当调用其他函数和返回之间没有任何事情发生时,会发生尾调用。它可以是返回前的最后一行,而不是返回前的最后一行或返回它自己。
例如,
} else {
x = gcd(a,b);
return x;
}
是一个尾调用,因为x的值是未修改的(没有发生)。
另一方面,
} else {
x = gcd(a,b);
return x + 1;
}
这不符合TCO的条件,因为修改了返回值 - 正在发生。
但乐趣才刚刚开始!我们来谈谈C ++和析构函数。请考虑以下代码:
int do2();
int do() {
std::string x;
// ...
return do2();
}
这是一个尾声吗?第一印象 - 是的,它是。什么都没发生,对吧?第二印象 - 不,它不是!析构函数x
需要发生!第三印象 - 是的,它是 - 因为在调用之后看不到x
的编译器可以在之前轻易破坏x
。
但是,看看那个:
int do2(const std::string& );
int do() {
std::string x;
// ...
return do2(x);
}
这不是尾声! x必须比do2
更长,所以回到我原来的(故意模糊的)定义,某事正在发生。
尾巴电话很有趣!