【发布时间】:2021-11-25 15:45:19
【问题描述】:
我的函数是尾递归吗?如果是这样,为什么/为什么不呢?我在理解这个概念时遇到了一些困难,因此非常感谢任何帮助。
struct link
{
int value; //data
link_t *next; //link
};
struct list
{
link_t *first;
link_t *last;
};
int list_size_count(link_t *first, int acc)
{
if (first != NULL)
{
return (acc + list_size_count((first->next), 1));
}
return acc;
}
int linked_list_size(list_t *list)
{
return list_size_count((list->first),0);
}
【问题讨论】:
-
你怎么看?你得出什么结论?你为此付出了什么努力?
-
一般来说,tail call是指一个函数的返回值是另一个函数调用的直接结果,返回值被直接 作为新的返回值。这增加了执行尾调用优化的机会,其中被调用函数直接返回到调用函数的调用者。这允许在调用函数之前回收当前堆栈帧。但这只有在您的编译器支持尾调用优化时才会发生。
-
在你发布的代码中,唯一的尾调用在
linked_list_size,它调用并返回list_size_count的结果。递归函数list_size_count不包含尾调用(因此不是尾递归)。可以通过将acc的add折叠到函数本身转化为尾递归函数,这样返回值在返回前不需要在调用者中修改。 -
更重要的是编译器是否真的可以优化递归。通常,编译器只有在尾调用递归时才能做到这一点。这意味着任何不是尾调用的递归都不应该在任何情况下使用,因为它非常慢,非常危险并且通常不可读。这绝对没有任何收获。
-
@TomKarzes 我该怎么做?
标签: c recursion linked-list tail-recursion tail