總目錄:http://www.reibang.com/p/e406a9bc93a9
Python - 子目錄:http://www.reibang.com/p/50b432cb9460
遞歸函數(shù)
在函數(shù)內(nèi)部辽装,可以調(diào)用其他函數(shù)。如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身,這個(gè)函數(shù)就是遞歸函數(shù)淋样。
這個(gè)就是一個(gè)例子:
如果不理解遞歸的意義俭尖,以為會(huì)輸出:
3
2
1
0
------
0
但是讓我們仔細(xì)分析一下運(yùn)行的過(guò)程:
仔細(xì)分析遞歸的意義层释,并且結(jié)合遞歸的運(yùn)算方式亏狰,正確的輸出結(jié)果為:
3
2
1
0
------
0
1
2
3
遞歸的第一個(gè)難點(diǎn)便是甩恼,進(jìn)入循環(huán)時(shí)后面的語(yǔ)句在循環(huán)結(jié)束后也要執(zhí)行。
比如這個(gè)例子三次遞歸孤澎,可以理解為三層嵌套届氢,第三層嵌套結(jié)束后會(huì)執(zhí)行第二次嵌套最后的語(yǔ)句,第一層同理覆旭。
遞歸函數(shù)的優(yōu)點(diǎn)是定義簡(jiǎn)單缰泡,邏輯清晰稳捆。理論上,所有的遞歸函數(shù)都可以寫(xiě)成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰绅喉。
使用遞歸函數(shù)需要注意防止棧溢出禽额。在計(jì)算機(jī)中孽糖,函數(shù)調(diào)用是通過(guò)棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的钙蒙,每當(dāng)進(jìn)入一個(gè)函數(shù)調(diào)用,棧就會(huì)加一層棧幀腕铸,每當(dāng)函數(shù)返回惜犀,棧就會(huì)減一層棧幀。由于棧的大小不是無(wú)限的狠裹,所以虽界,遞歸調(diào)用的次數(shù)過(guò)多,會(huì)導(dǎo)致棧溢出酪耳。
最簡(jiǎn)單的例子就是數(shù)值遞歸運(yùn)算:
def fact(n):
????if n==1:
????????return 1
????return n * fact(n -1)
如果print(fact(5))的話會(huì)輸出120浓恳,但是print(fact(1000))呢,會(huì)報(bào)錯(cuò)碗暗。這不是程序哪里錯(cuò)誤了颈将,這就是遞歸太多導(dǎo)致棧溢出。
解決遞歸導(dǎo)致棧溢出的方法就是進(jìn)行尾遞歸優(yōu)化言疗,但是大多數(shù)編程語(yǔ)言都沒(méi)有進(jìn)行尾遞歸優(yōu)化晴圾,所以通過(guò)尾遞歸調(diào)用一樣會(huì)導(dǎo)致棧溢出:
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)