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

时间:2010-10-21 09:44:11

标签: c# algorithm recursion functional-programming performance

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

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

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

5 个答案:

答案 0 :(得分:16)

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

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

查看Creating Thread with Custom Stack Size

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

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:5)

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

当你需要递归时,你需要它,比如深度优先树走路或递归下降解析。

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