五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

5.4 遞歸函數(shù)

2021-08-24 16:54 作者:海鷗之道  | 我要投稿

在函數(shù)內(nèi)部,可以調(diào)用其他函數(shù)。如果一個函數(shù)在內(nèi)部調(diào)用自身本身,這個函數(shù)就是遞歸函數(shù)。

舉個例子,我們來計算階乘n! = 1 x 2 x 3 x ... x n,用函數(shù)fact(n)表示,可以看出:

所以,fact(n)可以表示為n x fact(n-1),只有n=1時需要特殊處理。

于是,fact(n)用遞歸的方式寫出來就是:

def fact(n):

? ?if n==1:

?? ????return 1

? ?return n * fact(n - 1)

上面就是一個遞歸函數(shù)??梢栽囋嚕?/p>

>>> fact(1)

1

>>> fact(5)

120

>>> fact(100)

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

如果我們計算fact(5),可以根據(jù)函數(shù)定義看到計算過程如下:


遞歸函數(shù)的優(yōu)點(diǎn)是定義簡單,邏輯清晰。理論上,所有的遞歸函數(shù)都可以寫成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰。

使用遞歸函數(shù)需要注意防止棧溢出。在計算機(jī)中,函數(shù)調(diào)用是通過棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,每當(dāng)進(jìn)入一個函數(shù)調(diào)用,棧就會加一層棧幀,每當(dāng)函數(shù)返回,棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調(diào)用的次數(shù)過多,會導(dǎo)致棧溢出??梢栽囋?code>fact(1000):

>>> fact(1000)?

Traceback (most recent call last):

?File "<stdin>", line 1, in <module>

?File "<stdin>", line 4, in fact ?...

?File "<stdin>", line 4, in fact?

RuntimeError: maximum recursion depth exceeded in comparison

解決遞歸調(diào)用棧溢出的方法是通過尾遞歸優(yōu)化,事實(shí)上尾遞歸和循環(huán)的效果是一樣的,所以,把循環(huán)看成是一種特殊的尾遞歸函數(shù)也是可以的。

尾遞歸是指,在函數(shù)返回的時候,調(diào)用自身本身,并且,return語句不能包含表達(dá)式。這樣,編譯器或者解釋器就可以把尾遞歸做優(yōu)化,使遞歸本身無論調(diào)用多少次,都只占用一個棧幀,不會出現(xiàn)棧溢出的情況。

上面的fact(n)函數(shù)由于return n * fact(n - 1)引入了乘法表達(dá)式,所以就不是尾遞歸了。要改成尾遞歸方式,需要多一點(diǎn)代碼,主要是要把每一步的乘積傳入到遞歸函數(shù)中:

def fact(n):

? ?return fact_iter(n, 1)

def fact_iter(num, product):

? ?if num == 1:

? ? ? ?return product

?? return fact_iter(num - 1, num * product)

可以看到,return fact_iter(num - 1, num * product)僅返回遞歸函數(shù)本身,num - 1num * product在函數(shù)調(diào)用前就會被計算,不影響函數(shù)調(diào)用。

fact(5)對應(yīng)的fact_iter(5, 1)的調(diào)用如下:

尾遞歸調(diào)用時,如果做了優(yōu)化,棧不會增長,因此,無論多少次調(diào)用也不會導(dǎo)致棧溢出。

遺憾的是,大多數(shù)編程語言沒有針對尾遞歸做優(yōu)化,Python解釋器也沒有做優(yōu)化,所以,即使把上面的fact(n)函數(shù)改成尾遞歸方式,也會導(dǎo)致棧溢出。

小結(jié)

  • 使用遞歸函數(shù)的優(yōu)點(diǎn)是邏輯簡單清晰,缺點(diǎn)是過深的調(diào)用會導(dǎo)致棧溢出。

  • 針對尾遞歸優(yōu)化的語言可以通過尾遞歸防止棧溢出。尾遞歸事實(shí)上和循環(huán)是等價的,沒有循環(huán)語句的編程語言只能通過尾遞歸實(shí)現(xiàn)循環(huán)。

  • Python標(biāo)準(zhǔn)的解釋器沒有針對尾遞歸做優(yōu)化,任何遞歸函數(shù)都存在棧溢出的問題。


5.4 遞歸函數(shù)的評論 (共 條)

分享到微博請遵守國家法律
灵石县| 霍邱县| 扶绥县| 白沙| 光山县| 浙江省| 镶黄旗| 定边县| 博客| 墨江| 娱乐| 区。| 玛曲县| 囊谦县| 布尔津县| 陵水| 普兰县| 大方县| 沙坪坝区| 忻城县| 北安市| 乌恰县| 丹寨县| 天全县| 灌阳县| 翼城县| 富蕴县| 大竹县| 永城市| 汾西县| 和顺县| 朝阳县| 凤山市| 潮州市| 正宁县| 漯河市| 冕宁县| 瑞金市| 平远县| 施秉县| 黑龙江省|