函數(shù)之 遞歸函數(shù)
def fact(n):
if n == 1:
return 1
else:
return n * fact(n-1)
print(fact(1))
# print(fact(2))
# print(fact(10))
# print(fact(100))
# print(fact(900))
# print(fact(1000)) # 報(bào)錯(cuò) 遞歸棧溢出
# 解決遞歸調(diào)用棧溢出的方法是通過尾遞歸優(yōu)化,事實(shí)上尾遞歸和循環(huán)的效果是一樣的,所以,把循環(huán)看成是一種特殊的尾遞歸函數(shù)也是可以的。
# 尾遞歸是指,在函數(shù)返回的時(shí)候,調(diào)用自身本身,并且,return語句不能包含表達(dá)式。這樣,編譯器或者解釋器就可以把尾遞歸做優(yōu)化,使遞歸本身無論調(diào)用多少次,都只占用一個(gè)棧幀,不會(huì)出現(xiàn)棧溢出的情況。
小結(jié)
使用遞歸函數(shù)的優(yōu)點(diǎn)是邏輯簡(jiǎn)單清晰,缺點(diǎn)是過深的調(diào)用會(huì)導(dǎo)致棧溢出。
針對(duì)尾遞歸優(yōu)化的語言可以通過尾遞歸防止棧溢出。尾遞歸事實(shí)上和循環(huán)是等價(jià)的,沒有循環(huán)語句的編程語言只能通過尾遞歸實(shí)現(xiàn)循環(huán)。
Python標(biāo)準(zhǔn)的解釋器沒有針對(duì)尾遞歸做優(yōu)化,任何遞歸函數(shù)都存在棧溢出的問題。
練習(xí)
漢諾塔的移動(dòng)可以用遞歸函數(shù)非常簡(jiǎn)單地實(shí)現(xiàn)。
B=[] #設(shè)置操作過程列表
def move(n, a, b, c):
global s
if n==1:
buzhou=a+str(n)+'-->'+c+str(n) #一個(gè)圓盤需要從A到C操作步驟
B.append(buzhou) #向列表中添加操作步驟
return
move(n-1,a,c,b) # 將A柱的n-1個(gè)盤移到B柱
buzhou=a+str(n)+'-->'+c+str(n) #將A柱的第n個(gè)盤移到C柱操作步驟
B.append(buzhou) #向列表中添加操作步驟
move(1,a,b,c) #將A柱上最后一個(gè)盤移到C柱=
move(n-1,b,a,c) #將過渡柱子B上n-1個(gè)圓盤B移動(dòng)到目標(biāo)柱子C
move(3,'A','B','C') #2**64-1,64次太大,這里用6個(gè)盤子
print('共需操作'+str(len(B))+'次','操作過程為',B)#計(jì)算6個(gè)盤子的步驟數(shù)及操作過程
關(guān)注一波!喜歡一波!本人是前端菜鳥,正在做自己的個(gè)人博客鄧鵬的博客,歡迎來交流學(xué)習(xí), 使用的技術(shù) vue + koa2 + mysql + php + nginx!