用通俗的話來講就像問路,張三問李四,李四問王五,王五問趙六 趙六知道答案回覆了王五,王五回覆了李四,李四回覆了張三,問路結束函數
官方的定義是一個函數調用其自己優化
1.必須有一個明確的中止條件spa
2.每次更深刻一層遞歸時,問題規模要比上次遞歸都應有所減少code
3.遞歸次數不能太多,不然會形成棧溢出blog
遞歸函數在某些時候具備代碼邏輯十分清晰的效果,好比在算數的階乘的時候。階乘的定義爲n! = 1 × 2 × 3 × … × n,示例代碼以下所示:遞歸
def jiecheng(n): if n==1: return n else: return n*jiecheng(n-1) res = jiecheng(5) print(res) #打印結果爲120
由於暫時寫不出例子,用如下代碼來說解尾遞歸優化是怎麼一回事兒class
#不屬於尾遞歸調用 def test1(n): if n==1: return n else: return n*test1(n-1)
#屬於尾遞歸調用 def test2(n): if n==1: return n else: return test2(n-1)
以上兩行代碼的區別就在於最後一步,不屬於尾遞歸調用的那個最後一行代碼實際上執行步驟以下test
res = test1(n-1) #1變量
res = n* res #2方法
在執行第一步的時候跳入第二層函數的時候須要保存第一層函數的位置,變量等信息在棧中
而屬於尾遞歸調用的最後一行代碼執行步驟以下
res = test1(n-1) #1
在跳入第二層函數的時候第一層的函數實際上已經結束,不須要保存第一層函數相關的全部信息了。
因此尾遞歸調用能夠減輕棧的負荷