直接上例子说话:
计算斐波纳契数的递归算法
def fib(n)
return 0 if n == 0
return 1 if n == 1
return fib(n-2) + fib(n-1)
end
计算斐波纳契数的迭代器算法 (正是看到这个示例,深有感触)
def fib(n)
a, b = 0, 1
n.times do
a, b = b, a + b
end
a
end
计算阶乘递归算法
def fac(n)
return 1 if n == 1
return n * fac(n-1)
end
def fac(n)
(1..n).reduce(:*)
end
在没有学 Ruby 之前 (甚至在学了 Ruby 之后), 我仍然可能会习惯性的使用前者。
我想性能不用说了,递归的性能和迭代器那相差老远了去了!!
现在想讨论的问题是:
是不是所有的递归算法,都可以 (有一个途径) 使用迭代器进行替换?? (在 Ruby 语言下)
如果以上结论正确的话,那就是否就意味着下面的定律是成立的:
不要用递归, 他总可能成为你的项目的性能瓶颈
http://stackoverflow.com/questions/72209/recursion-or-iteration 我喜欢这里的一句话 Loops may achieve a performance gain for your computer. Recursion may achieve a performance gain for your programmer. Choose which is more important in your situation!
http://stackoverflow.com/questions/72209/recursion-or-iteration 我喜欢这里的一句话 Loops may achieve a performance gain for your computer. Recursion may achieve a performance gain for your programmer. Choose which is more important in your situation!
http://stackoverflow.com/questions/72209/recursion-or-iteration 我喜欢这里的一句话 Loops may achieve a performance gain for your computer. Recursion may achieve a performance gain for your programmer. Choose which is more important in your situation!
http://stackoverflow.com/questions/72209/recursion-or-iteration 我喜欢这里的一句话 Loops may achieve a performance gain for your computer. Recursion may achieve a performance gain for your programmer. Choose which is more important in your situation!
我觉得这显然不成立,如果递归可以完全用迭代 (循环) 代替,那递归就不会成为一种经典算法了。这在任何语言都是一样的。不能被 ruby 优秀的语法糖给欺骗了。😊
有机械的方式将所有递归改写成循环,不过结果是在堆上分配一个栈,一些函数式语言就是这么做的,让你放心使用递归而无需担心栈溢出的问题。 某些不需要保存中间状态的递归可以改成不带栈的循环,有专门研究这个的。
做网站遇到的问题基本都有现成套路去搞... 没必要全递归或全不递归。 就算是没有循环结构的函数式语言也有仿造 foreach 和 while 的方案,怎么好理解就怎么写。
理论上(算法导论可以找到其说明),每种尾递归都可以用一个迭代过程来替换。
递归之所以经典,是因为可理解性与简洁性,即符合人类的思维,又与宇宙的递归设计层层相扣。
我以为,Ruby 里面大可以多用递归,符合它的设计哲学:For Funny.
第一个例子之所以性能差又不是递归导致的,是因为重复计算,第二个例子,用递归也没有太大性能问题。PS: 你说在没有学 Ruby 之前,你会用前一种算法,冒昧问一句你之前都是用什么语言编程的?
第一个例子之所以性能差又不是递归导致的,是因为重复计算,第二个例子,用递归也没有太大性能问题。PS: 你说在没有学 Ruby 之前,你会用前一种算法,冒昧问一句你之前都是用什么语言编程的?
第一个例子之所以性能差又不是递归导致的,是因为重复计算,第二个例子,用递归也没有太大性能问题。PS: 你说在没有学 Ruby 之前,你会用前一种算法,冒昧问一句你之前都是用什么语言编程的?
只有原始递归才能转换为 O(n) 级别的运算,但是不能只从算法效率上看,需要看应用场景和易读性。 比如 fib 来说,可以用矩阵计算达到 O(lg(n))
require 'matrix'
M = Matrix[[1,1],[1,0]]
def fib(n)
(M**(n-1))[0,0]
end
但是在 n 较小的情况下,还不如直接递归+Memorization 来得性能好和容易理解
嗯。这话有道理呀。
谢谢指正,之前的确没有注意到重复调用的问题,原来我之前对于递归的误会还是蛮大的. 之前用过 Pascal.
不过,性能上还是后者好一些. #13 楼 @quakewang 牛呀~ 不过,说实话我看不懂。我想搞 Rails 还了解这玩意儿的程序员,少之又少了吧. 当年,数学也算是俺绝对强项,可惜荒废了呀。