1. 程式人生 > >第022講:函式:遞迴是神馬

第022講:函式:遞迴是神馬

目錄

測試題

0. 遞迴在程式設計上的形式是如何表現的呢?

1. 遞迴必須滿足哪兩個基本條件?

2. 思考一下,按照遞迴的特性,在程式設計中有沒有不得不使用遞迴的情況?

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

4. 請聊一聊遞迴的優缺點(無需官方陳詞,想到什麼寫什麼就可以)

5. 拿手機拍一張“遞迴自拍照片”

動動手

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

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

3. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!


測試題

0. 遞迴在程式設計上的形式是如何表現的呢?

答:在程式設計上,遞迴表現為函式呼叫本身這麼一個行為。

舉個例子(遞迴求階乘):

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

number = int(input('請輸入一個整數:'))
result = factorial(number)

print("%d的階乘是:%d" % (number, result))

1. 遞迴必須滿足哪兩個基本條件?

答:一、函式呼叫自身

      二、設定了正確的返回條件

2. 思考一下,按照遞迴的特性,在程式設計中有沒有不得不使用遞迴的情況?

答:例如漢諾塔,目錄索引(因為你永遠不知道這個目錄裡邊是否還有目錄),快速排序(二十世紀十大演算法之一),樹結構的定義等如果使用遞迴,會事半功倍,否則會導致程式無法實現或相當難以理解。

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

答:小甲魚在課程的開頭說“普通程式設計師用迭代,天才程式設計師用遞迴”這句話是不無道理的。

但是你不要理解錯了,不是說會使用遞迴,把所有能迭代的東西用遞迴來代替就是“天才程式設計師”了,恰好相反,如果你真的這麼做的話,那你就是“烏龜程式設計師”啦。

為什麼這麼說呢?不要忘了,遞迴的實現可以是函式自個兒呼叫自個兒,每次函式的呼叫都需要進行壓棧、彈棧、儲存和恢復暫存器的棧操作,所以在這上邊是非常消耗時間和空間的。

另外,如果遞迴一旦忘記了返回,或者錯誤的設定了返回條件,那麼執行這樣的遞迴程式碼就會變成一個無底洞:只進不出!所以在寫遞迴程式碼的時候,千萬要記住口訣:遞迴遞迴,歸去來兮!出來混,總有一天是要還的!

4. 請聊一聊遞迴的優缺點(無需官方陳詞,想到什麼寫什麼就可以)

優點:

1)遞迴的基本思想是把規模大的問題轉變成規模小的問題組合,從而簡化問題的解決難度(例如漢諾塔遊戲)。

2)有些問題使用遞迴使得程式碼簡潔易懂(例如你可以很容易的寫出前中後序的二叉樹遍歷的遞迴演算法,但如果要寫出相應的非遞迴演算法就不是初學者可以做到的了。)

缺點:

1)由於遞迴的原理是函式呼叫自個兒,所以一旦大量的呼叫函式本身空間和時間消耗是“奢侈的”(當然法拉利也奢侈,但還是很多人趨之若鶩)。

2)初學者很容易錯誤的設定了返回條件,導致遞迴程式碼無休止呼叫,最終棧溢位,程式崩潰。

5. 拿手機拍一張“遞迴自拍照片”


動動手

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

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

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

def gcd(x, y):
    if y:
        return gcd(y, x%y)
    else:
        return x
    
print(gcd(4, 6))

3. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!

(1)什麼時候遞迴

有呼叫函式自身的行為

有正確的返回條件

(2)遞迴求階乘

寫一個求階乘的函式:

首先看不用遞迴的程式:

def factorial(n):
	if n ==0 or n == 1:
		result = 1
		return result
	else:
		result = n
		for i in range(1,n):
			result *= i
		return result

然後使用遞迴實現:

def factorial(n):
	if n == 1 or n == 0:
		return 1
	else:
		return n * factorial(n-1)