是否应该避免在C / C ++中使用函数的递归调用?
我从事机器学习/数据挖掘,因此让我的代码可扩展至关重要。
当我使用Java时,我尽可能避免使用递归调用,因为我经常让我的调用堆栈溢出。虽然有控制分配给调用堆栈的内存量的选项,但我认为让我的程序依赖于较少数量的参数是更理想的。因此,当很清楚如何在没有递归调用的情况下实现,可能使用自己管理的堆栈,我这样做了。但即使在Java中,我也不确定这是一门正确的学科。
据我所知,C / C ++中没有调用堆栈,所以我不担心溢出它。因此,我很好奇:在程序的可扩展性方面,是否会尝试避免使用递归,或者是鼓励它,还是特定于问题?
答案 0 :(得分:12)
这个问题没有一个正确答案。对于某些问题,递归效果很好。对于其他人,它没有。
据我所知,C / C ++中没有调用堆栈
为了清楚起见,这是不正确的:在我知道的所有C和C ++实现中, 是一个调用堆栈。
答案 1 :(得分:7)
据我所知,C / C ++中没有调用堆栈,所以我不担心 关于溢出它
咦?当然 标准 没有谈论调用堆栈,但实际上大多数(如果不是全部)实现都有一个。
现在,应该避免递归吗?首先,众所周知,每个递归函数都可以迭代重写(即没有递归)。而且,有时迭代解决方案比递归解决方案更快。但是对于某些任务,例如图中的DFS,递归是如此简单和有用,你不应该避免使用它 ,除非 你有充分的理由不这样做。同一个DFS的迭代解决方案几乎一样简单,但需要更多的输入......
我的2 c。
答案 2 :(得分:3)
我经常让我的调用堆栈溢出
那是你的错误。
正确使用时,递归是一个非常有用的结构。特别是在需要使用可变大小的数据结构集的情况下。限制递归是微不足道的:
int recurse(int maxlimit, ...)
{
if (!--maxlimit) return false; // and throw an exception or something
...
return completed ? finalvalue : recurse(maxlimit, ...);
}
答案 3 :(得分:3)
C& C中的调用堆栈C ++有点像C ++ 中的vtable在某方面 - 据我所知,它没有在标准中提及,即,实现不是强制性的,但是出于所有实际目的,它几乎总是被实现那样。
当然,有一些深奥的架构,特别是在嵌入式领域,可能会避开堆栈。 PIC是堆栈不友好架构的一个例子,一些微型微控制器不支持堆栈,最不直接。在某些情况下,无论如何都可以消除堆栈的使用(内联函数或对函数调用的积极优化,使用寄存器作为局部变量而不是堆栈空间)。
无论如何,对于你的问题......这是一个非常主观的问题,通常归结为一个问题:你能负担得起吗?
如果你有足够的堆栈空间并且递归不会足以让你的堆栈崩溃,那么递归通常是正确的选择。不总是,但经常。
但您必须了解您的架构,平台,工具集等,并了解您的堆栈有多大。例如,对于许多多任务嵌入式系统,您的堆栈大小是在创建线程/任务时确定的,并且不会“根据需要增长”。其他简单(嵌入式)系统仅使用单个堆栈,或者可能使用一个“后台”堆栈和一个中断堆栈。还有一些允许堆栈根据需要在限制范围内增长,这取决于处理器和处理器。操作系统。
如果你是来自Java背景,如果这种讨论对你来说很新,我并不感到惊讶。
答案 4 :(得分:1)
递归可以是表达算法的一种非常优雅的方式。 C / C ++的主要缺点是堆栈溢出的可能性。
以下是C / C ++的经验法则:
如果递归不是尾调用,则深度需要与数据大小呈线性关系。
例如,如果要递归执行二叉树的DFS,则必须平衡该树,使得递归深度为O(log n)。这确保没有堆栈溢出。不要使用非尾递归来遍历链表(O(n)深度)。