应该避免在C/ c++中使用递归调用吗?
Should one avoid using recursive call in C/C++?
应该避免在C/c++中使用递归函数调用吗?
我的工作是机器学习/数据挖掘,所以让我的代码可扩展对我来说非常重要。
当我使用Java时,我尽量避免使用递归调用,因为我经常使调用堆栈溢出。虽然有一些选项可以控制分配给调用堆栈的内存量,但我认为让我的程序依赖于更少的参数是更可取的。因此,当清楚如何实现不递归调用时,可能使用我自己管理的堆栈,我就这样做了。但是,即使在Java中,我也不确定这是否是一个正确的学科。
据我所知,在C/c++中没有调用堆栈,所以我不会担心溢出它。因此,我很好奇:在程序的可伸缩性方面,是否会尝试避免使用递归,或者鼓励使用递归,或者它是特定于问题的?
这个问题没有唯一的正确答案。对于某些问题,递归工作得非常好。
据我所知,在C/c++中没有调用堆栈
澄清一下,这是不正确的:在我所知道的所有C和c++实现中,是一个调用堆栈。
据我所知,在C/c++中没有调用堆栈,所以我不会担心关于溢出
啊?当然,标准没有讨论调用堆栈,但确实在大多数(如果不是全部)实现中都有调用堆栈。
现在,应该避免递归吗?首先,众所周知,每个递归函数都可以迭代地重写(即不需要递归)。而且,有时候迭代解比递归解快。但是对于某些任务,例如图中的DFS,递归是如此简单和有用,以至于您不应该避免使用它,除非您有很好的理由不使用它。相同DFS的迭代解决方案几乎同样简单,但需要更多的输入…
C &c++在一个方面有点像c++ 中的虚函数表——据我所知,在标准中没有提到它,也就是说,实现不是强制的,但出于所有实际目的,它几乎总是这样实现的。
当然有一些深奥的体系结构,特别是在嵌入式世界中,可能会避开堆栈。PIC是堆栈不友好架构的一个例子,一些微型微控制器不支持堆栈,至少不直接支持堆栈。在某些情况下,堆栈的使用是可以消除的(内联函数或对函数调用的激进优化,使用局部变量寄存器而不是堆栈空间)。
不管怎样,对于你的问题…这是一个非常主观的问题,通常可以归结为一个问题:你买得起吗?如果你有足够的堆栈空间,并且递归不会深到破坏堆栈,递归通常是正确的选择。不总是,但经常。
但是你必须了解你的架构,你的平台,你的工具集等等,并且知道你的堆栈有多大。例如,对于许多多任务嵌入式系统,堆栈大小是在创建线程/任务时确定的,它不会"按需增长"。其他简单的(嵌入式)系统只使用单个堆栈,或者一个"后台"堆栈和一个中断堆栈。还有一些允许堆栈根据需要在限制内增长,这取决于处理器。操作系统。
如果您有Java背景,对于这种讨论对您来说是新的,我并不感到惊讶。
调用栈经常溢出
那就是你的错了。
如果使用正确,递归是一个非常有用的结构。特别是当您需要处理一组可变大小的数据结构时。限制递归是微不足道的:int recurse(int maxlimit, ...)
{
if (!--maxlimit) return false; // and throw an exception or something
...
return completed ? finalvalue : recurse(maxlimit, ...);
}
递归可以是一种非常优雅的表达算法的方式。C/c++的主要缺点是可能发生堆栈溢出。
下面是C/c++的经验法则:如果递归不是尾部调用,那么深度需要是数据大小的次线性
例如,如果你要递归地对二叉树进行DFS,那么该树必须是平衡的,这样递归深度为O(log n)。这确保不会出现堆栈溢出。不要使用非尾递归来遍历链表(O(n)深度)。
- 返回递归调用和仅递归调用的区别
- 使用静态变量的递归调用的不同输出
- 复制构造函数中的递归调用
- 为什么编译器将其解析为函数指针而不是递归调用?
- 如何在 c++ 的类中递归调用函数方法?
- 了解使用堆栈实现队列的递归调用机制
- 如何通过函数指针递归调用类成员函数?
- 条件加倍时的递归调用
- 对可变参数函数的递归调用的链接器错误
- 将多个非原始递归调用转换为迭代解决方案
- 分段错误(核心转储)错误C++递归调用
- 无全局变量或功能参数的递归调用
- 在递归DP中,通过存储变量来分解递归调用:效率低下
- C - 为什么合并函数在递归调用后会逆转数组
- 递归调用中出现错误"[Error] expression list treated as compound expression in initializer [-fpermissive]"
- C / SFML:使用两个递归调用在屏幕上打印凸形形状仅显示第一个递归调用中的形状,而不是第二个
- C++中具有 100000 个递归调用的运行时错误
- 递归调用可变参数模板函数重载时的不明确调用
- 如何在 c++ 中递归调用类
- 带有两个递归调用的递归算法的时间复杂性