应该避免在C / C ++中使用递归调用吗?

时间:2011-08-03 16:13:57

标签: c++ c recursion

是否应该避免在C / C ++中使用函数的递归调用?

我从事机器学习/数据挖掘,因此让我的代码可扩展至关重要。

当我使用Java时,我尽可能避免使用递归调用,因为我经常让我的调用堆栈溢出。虽然有控制分配给调用堆栈的内存量的选项,但我认为让我的程序依赖于较少数量的参数是更理想的。因此,当很清楚如何在没有递归调用的情况下实现,可能使用自己管理的堆栈,我这样做了。但即使在Java中,我也不确定这是一门正确的学科。

据我所知,C / C ++中没有调用堆栈,所以我不担心溢出它。因此,我很好奇:在程序的可扩展性方面,是否会尝试避免使用递归,或者是鼓励它,还是特定于问题?

5 个答案:

答案 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)深度)。