Python之递归函数
前言
說到遞歸,如果是從其他編程語言轉到 Python 的童鞋對這個詞一定不會陌生,在很多情況下,使用遞歸可以提高程序的可讀性,雖然可以完全避免編寫遞歸函數,轉而使用循環來代替,但是作為程序猿,至少必須要能夠讀懂其他人編寫的遞歸算法和函數吧。OK,廢話不多說,來看一下 Python 中遞歸函數的寫法。
定義
所謂遞歸,就是調用函數自身。
簡單的說就是函數自己調用自己。遞歸可能難以理解,也可能非常簡單,這取決于對它的熟悉程度。
下面是一個遞歸函數的定義:
這個遞歸定義顯然什么都沒有做,如果運行該函數的結果就是一段時間后程序就崩掉了。因為每次調用函數都將會消耗一些內存,當內存爆滿就自然就掛了。
這個函數中的遞歸成為無窮遞歸,就好比一個 while 死循環,從理論上說它將永遠不會結束,這顯然不是我們想要的結果。
所以正常的遞歸函數通常包含以下兩個部分;
1.基線條件(針對最小的問題):滿足這種條件時函數將直接返回一個值。
2.遞歸條件:包含一個或多個調用,這些調用旨在解決問題的一部分。
這里的關鍵是,通過將問題分解為較小的部分,可避免遞歸沒完沒了,因為問題終將被分解成基線條件可以解決的最小問題。
OK,以上的定義和描述可能對于一個剛接觸遞歸的人來說有些難以理解,接下來通過幾個示例來看看遞歸的用法。
遞歸經典案例
計算階乘
階乘定義:n 的階乘為 n*(n-1)*(n-2)*…*1
那么要計算階乘,用傳統的循環方式寫法如下:
上述循環的思路大概是:首先將 result 設置成 n,然后通過循環,將 result 依次乘以1~(n-1)的每個數字,最后返回結果。
而通過遞歸的方式如何實現呢,再看階乘的算法,n 的階乘其實相當于 n 乘以(n-1)的階乘,而1的階乘為1。
通過以上分析,來看看通過遞歸來實現階乘的寫法:
很明顯,通過遞歸來實現同樣算法,代碼非常簡單,并且可讀性也很好。這是前述定義的直接實現,只是別忘了函數調用factorial(n)和factorial(n-1) 是不同的實體。
計算冪
定義一個數字的整數次冪,有多種方式,先來看個簡單的定義:power(x,n)(x 的 n 次冪)是將數字 x 自乘以 n-1次的結果,即將 n 個 x 相乘。
傳統的寫法,通過循環來實現:
這是一個非常簡單的小型函數,可將定義修改成遞歸的形式:
對于任何數字的0次冪都是1
當 n 大于0時,power(x,n)為 x和 power(x,n-1)的乘積。
那么來看看遞歸的寫法:
def power(x,n):if n == 0:return 1else:return x*power(x,n-1)二分法查找
二分法查找,這是一個非常經典的查找算法,所謂的二分法,就是讓每次查找的范圍減半,這樣查找效率非常的高,比如說一個猜數游戲,從1~100數字中猜出對方想好的一個數字,如果從1到100一個個的猜,肯定能猜對,最多會猜100次,那么最少需要猜多少次呢,通過二分法實際上只需要7次就能猜出正確答案。
結合二分法的定義引出遞歸的定義和實現。
1.如果上限和下限相同,就說明它們都指向數字所在的位置,因此將該數字返回。
2.否則,找出區間的中間位置(上限和下限的平均值),再將數字確定是在左半部分還是有半部分,然后繼續在數字所在的那部分中查找。
OK,接下來看看遞歸實現二分法算法:
def search(seq,number,lower = 0,upper = None):if upper is None:upper = len(seq) - 1if lower == upper:assert number == seq[upper]return upperelse:middle = (lower + upper) // 2if number > seq[middle]:return search(seq,number,middle + 1,upper)else:return search(seq,number,lower,middle)這里將上限和下限值定義成可選,如果不指定上下限值,那么默認為序列的開頭和結尾位置。該遞歸的實現完全由上面的定義一致。
來看看效果:
返回結果:
[1, 23, 24, 32, 35, 38, 76, 89] 3 7二分法在對于一個非常大的序列中使用效率非常高,如果使用循環的方式一個個的去找,對于序列中元素較少的情況下還好,如果數據量非常大,查詢效率就很低了。
由此可見,遞歸的寫法非常簡潔,合理使用遞歸程序的可讀性將會大大的提高。
總結
以上是生活随笔為你收集整理的Python之递归函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python之函数的收集参数和分配参数用
- 下一篇: 简单理解Python中的if __nam