在C#中,在算法中使用递归函数是一种好习惯吗?

在许多使用递归的函数语言中被认为是一种很好的实践。 我认为这很好,因为编译器优化了函数式语言的代码。

但是在创建算法时,在C#中使用递归是一种好习惯吗? 就C#而言,是否正确,递归算法将导致您的堆栈增长非常显着(如果调用量非常大)并且这根本不会快,并且可能导致堆栈溢出。 或者还有一些优化可以使递归函数高效?

如果您在使用函数语言中的递归和C#的算法之间进行一些比较(速度,内存,可读性),我将不胜感激。

不使用递归会导致您使用自己的“堆栈”重写算法,最终在执行时会遇到类似的情况。

您可以根据算法的需要自定义堆栈大小,但是如果您查看WPF / Silverlight和普通的UI相关算法,它们本质上都是递归的,每次点击,每次按键和每个通知都会经过许多递归方法。

查看使用自定义堆栈大小创建线程 ,

尽管速度可能会因算法和复杂性而有所不同,但创建单独的非递归算法会使任务变得更复杂,因为您将使用列表,堆栈等自行执行所有数据存储操作。

这是一个非常设计与性能问题,如果你想要更好的性能,那么你的非递归算法将更快地执行,但是设计和实现这样的算法需要更长的时间。 如果你想要一个更快的解决方案,那么你可以编写递归算法,这将在执行速度较慢,但​​如果差异只有几毫秒或几微秒,那么它就不值得去做。

循环总是超越递归,因为堆栈总是比你的状态有更多的开销。 许multithreading操作都会大量走线,因此您会进一步下滑。

然而,可读性是一个很大的优点,所以我个人会使用递归,除非我需要每一滴性能,例如在图像处理操作中或我希望我的堆栈增长非常大 – 尽管堆栈溢出几乎完全是由于错误。

在Microsoft当前的C#编译器实现中,不进行尾调用优化。 这使得深度递归的function算法溢出堆栈。 虽然我不建议在C#中使用深度递归算法,但是不能深度递归的方法根本不会引起任何问题。

这篇文章的递归迭代器性能详细解释了递归版本与非递归操作之间的区别。 结果很有趣。 查看

函数式语言中递归的原因是良好的实践并不是因为尾递归优化; 这是一种很好的做法,因为它是表达大量算法的强大而简单的方法。 优化只是很好的,无论如何尾调用优化与所有递归函数无关。

因此,考虑到这一点,在c#中构建递归方法是非常好的做法,如果这是表达算法的最自然的方式。 显然,如果事实certificate存在堆栈深度问题,那么使其迭代可能是有意义的。 但是,采用自然递归算法并使其迭代而不首先知道它是一个问题是过早优化,并且可能使您的代码不必要地复杂并且难以阅读以换取很小的性能增益。

当您需要递归时,您需要它,例如深度优先树步行或递归下降解析。

如果你有一个选择,比如使用递归而不是循环,那么它可能是你所使用的语言的函数。保持简单。