遞歸函數兩種方式的區別

概述

遞歸函數都不陌生,比如計算n的階乘:

當然,有人可能會這麼寫:

上面兩種方式看著好像沒什麼區別,但是在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發現這種情況,會複用函數棧,也就是說,函數棧大概是這麼個情況:

遞歸函數兩種方式的區別

看著好像也沒啥區別,但是!因為可以直接返回,上圖的四個棧使用的都是同一個棧。


當遞歸返回的是遞歸調用,並且講調用直接返回,沒有參與運算等,就會被這樣優化,複用棧。


分享到:


相關文章: