递归函数两种方式的区别
概述
遞歸函數都不陌生,比如計算n的階乘:
function f($n){if($n <= 1) return 1;return $n * f($n-1); }當然,有人可能會這么寫:
function f($n, $result){if($n <= 1) return $result;return f($n-1, $n*$result); }上面兩種方式看著好像沒什么區別,但是在cpu眼中,可就不一樣了。
分析
函數在調用的時候會開辟一塊函數棧,用來保存函數的局部變量、參數、上一個棧的指針、返回值等信息,當函數調用結束后會銷毀。遞歸函數會一直遞歸下去,上層的函數棧一直不會銷毀,知道遞歸結束,全部退出。
舉個栗子,當調用f(3)的時候,對于上面的第一種情況,函數棧大概長這樣(僅保留參數和返回值,忽略其他內容):
文字描述就是:
f(1)=1
f(2)=2*f(1)=2*1=2
f(3)=3*f(2)=3*2=6
f(4)=4*f(3)=4*6=24
也就是每一次調用,都會保存本次的變量n以及遞歸調用的返回值,這就會導致如果遞歸的太神,就會開辟太多的內存。
如果使用第二種寫法,會有什么不同么?
套用剛才的分析,先用文字描述一下:
f(4, 1)=f(3, 4*1)=f(2, 3*4)=f(1, 2*12)=24
有沒有發現區別,區別就是,前一種寫法要保存一個局部變量n,而后一種寫法,都寫到下一個方法的參數中了。也就是說,第二種方式,可以直接返回下層方法,不需要退回去了。當然,cpu發現這種情況,會復用函數棧,也就是說,函數棧大概是這么個情況:
看著好像也沒啥區別,但是!因為可以直接返回,上圖的四個棧使用的都是同一個棧。
當遞歸返回的是遞歸調用,并且講調用直接返回,沒有參與運算等,就會被這樣優化,復用棧。
總結
以上是生活随笔為你收集整理的递归函数两种方式的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算矩阵中全1子矩阵的个数
- 下一篇: bootstrap上传图片可实现查看上一