1. 程式人生 > 實用技巧 >第23講:遞迴是神馬

第23講:遞迴是神馬

一 相關概念

1 定義:簡單點來說,就是一個函式直接或間接呼叫自身的一種方法,它通常把一個大型複雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。

  • 注意:遞迴具有危險性,很容易導致程式崩潰,所以一定要有邊界條件

2 能力:用有限的語語句來定義物件的無限集合。

3 內容:一般來說,遞迴需要有邊界條件、遞迴前進段和遞迴返回段。

  • 當邊界條件不滿足時,遞迴前進;當邊界條件滿足時,遞迴返回。:

4兩個基本條件

  • 函式呼叫自身
  • 設定了正確的返回條件

5 遞迴深度設定

>>> import sys
>>> sys.setrecursionlimit(200)

6 遞迴的優缺點

  • 優點
    • 遞迴的基本思想是把規模大的問題轉變成規模小的問題組合,從而簡化問題的解決難度(例如漢諾塔遊戲)。
    • 有些問題使用遞迴使得程式碼簡潔易懂(例如你可以很容易的寫出前中後序的二叉樹遍歷的遞迴演算法,但如果要寫出相應的非遞迴演算法就不是初學者可以做到的了)
  • 缺點
    • 由於遞迴的原理是函式呼叫自個兒,所以一旦大量的呼叫函式本身空間和時間消耗是“奢侈的”。
    • 初學者很容易錯誤的設定了返回條件,導致遞迴程式碼無休止呼叫,最終棧溢位,程式崩潰。

7 例子

  • 漢諾塔遊戲
  • 樹結構的定義
  • 謝爾賓斯基三角形
  • 女神自拍
  • 求階乘
  • 數字三角形
  • 二分查詢
  • 變位字(全排列)
  • 目錄索引
  • 快速排序

二 求階乘

1 程式碼:

 1 """ 求階乘
 2 """
 3 # -*- coding:utf-8 -*-
 4 
 5 """
 6 # 不用遞迴
 7 num = int(input("請輸入一個整數:"))
 8 
 9 sum =1 
10 for i in range(num+1):
11     if i > 0:
12         sum = sum * i
13 
14 print ("計算結果是:%d" % sum)
15 """
16 
17 # 使用遞迴的思想
18 def factor(n):
19     if n==1:
20         return
1 # 當n=1的時候結束遞迴 21 else: 22 return n * factor(n-1) # 當n!=1的時候逐層遞迴,即呼叫factor函式本身 23 24 number = int(input("請輸入一個整數:")) 25 result = factor(x) 26 print(f"{number}的階乘結果是{result}")

2 講解

3 補充:用遞迴去計算階乘問題或斐波那契數列是很糟糕的演算法,你知道為什麼嗎?

“普通程式設計師用迭代,天才程式設計師用遞迴”的意思不是說會使用遞迴,把所有能迭代的東西用遞迴來代替就是“天才程式設計師”了,恰好相反。因為遞迴的實現可以是函式自個兒呼叫自個兒,每次函式的呼叫都需要進行壓棧、彈棧、儲存和恢復暫存器的棧操作,所以在這上邊是非常消耗時間和空間的。另外,如果遞迴一旦忘記了返回,或者錯誤的設定了返回條件,那麼執行這樣的遞迴程式碼就會變成一個無底洞:只進不出!

三 課後作業

1使用遞迴編寫一個 power() 函式模擬內建函式 pow(),即 power(x, y) 為計算並返回 x 的 y 次冪的值。

1 def power(x, y):
2     if y:
3         return x * power(x, y-1)
4     else:
5         return 1
6     
7 print(power(2, 3))

2使用遞迴編寫一個函式,利用歐幾里得演算法求最大公約數,例如 gcd(x, y) 返回值為引數 x 和引數 y 的最大公約數。

1 def gcd(x, y):
2     if y:
3         return gcd(y, x%y)
4     else:
5         return x
6     
7 print(gcd(4, 6))