本文實例講述了Python遞歸及尾遞歸優化操作。分享給大家供大家參考,具體如下:
遞歸簡而言之就是自己調用自己。使用遞歸解決問題的核心就是分析出遞歸的模型,看這個問題能拆分出和自己類似的問題并且有一個遞歸出口。比如最簡單的就5的階乘,可以把它拆分成5*4!,然后求4!又可以調用自己,這種問題顯然可以用遞歸解決,遞歸的出口就是求1!,可以直接返回1。用Python實現如下:
def fact(n): if n==1: return n return n*fact(n - 1);print(fact(5))
運行結果:
120
在上面的求遞歸中,也有一定的缺點,假如說求1000!的階乘,會出現棧溢出的問題,因為在函數執行中,沒調用一個函數都會把當前函數的調用位置和內部變量保存在棧里面,由于棧的空間不是無限大(具體棧的最大空間還沒有查找到),假如說調用層數過多,就是出現棧溢出的情況。
這個時候就可以用尾遞歸優化來解決,尾調用的概念非常簡單,一句話就能說清楚,就是指某個函數的最后一步是調用另一個函數。
function f(x){ return g(x);}
尾遞歸優化后的階乘函數如下:
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)print(fact(5))print(fact(1000))
尾調用由于是函數的最后一步操作,所以不需要保留外層函數的調用記錄,因為調用位置、內部變量等信息都不會再用到了。所以尾遞歸優化可以有效的防止棧溢出,但是尾遞歸優化需要編譯器或者解釋器的支持,遺憾的是,大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化,所以,即使把上面的fact(n)函數改成尾遞歸方式,也會導致棧溢出。
漢諾塔問題也是一個經典的遞歸問題,具體題目就不說了,這里分析思路。假設hanoi(n, a, b, c)實現把a上的n個盤子移到c上。
當只有一個盤子時,直接從A移動到C即可
如果有3個盤子,可以這樣:
# A --> C
# A --> B
# C --> B
# A --> C
# B --> A
# B --> C
# A --> C
如果有很多盤子,我們分析一下該怎么移動,首先,我們需要把n-1個盤子移動到b中,才可以實現最簡單的一步,把a中最大的盤子移動到c中,具體怎么轉移到b中后面再討論。移動最大的盤子后,a和c都可以看成是空的,接下來,把b看成是a,把a看成是b,把a中的n-1個盤子(這里的n是已經減1的n)移動到b后,又可以移動第二大的盤子。這顯然是一個遞歸問題。
新聞熱點
疑難解答