1. 程式人生 > >python 之 遞歸

python 之 遞歸

沒有 解決問題 每次 參數 fff arc 例子 calc block

終於來到了這裏,這是一座山,山那邊都是神仙

定義:在一個函數裏調用函數本身

最好的例子就是,求階乘

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



while True:
    n = input(n>>)
    n = int(n)
    print(factorial(n))

遞歸最大層數

上面金典的例子運行的很成功

下面再來一個,是一個古老的故事,說,從前有個山,山裏有座廟,廟裏老和尚講故事, 講的什麽呢? 從前有個山,山裏有座廟,廟裏老和尚講故事, 講的什麽呢? 從前有個山,山裏有座廟,廟裏老和尚講故事, 講的什麽呢? 從前有個山,山裏有座廟,廟裏老和尚講故事, 講的什麽呢? 從前有個山,山裏有座廟,廟裏老和尚講故事, 講的什麽呢?

我們用代碼開實現一下

def story():
    s = """
    從前有個山,山裏有座廟,廟裏老和尚講故事,
    講的什麽呢?
    """
    print(s)
    
while True:
    story()

你運行了嗎?

shit,他報錯了,但是這個故事講的很完美。

RecursionError: maximum recursion depth exceeded while calling a Python object
這個錯誤是說,這個程序運行的代碼,超過了最大遞歸層數。

正如我們看到的,如果沒有外界阻力,它會一直運行下去

# 添加參數,設置停止條件
def calc(n, count):
    print(n, count)
    if count < 5:
        return calc(n/2, count+1)
    else:
        return n
print(calc(188,0))

因為每一次函數調用都會產生一個屬於它自己的名稱空間,如果一直調用下去,就會造成名稱空間占用太多內存的問題,直到內存被占滿,然後死機。

所以限制了他的最大遞歸層數,一般就是999層,

當然這個數字是可以修改的,修改方法很冷門,一般也不會有人去修改它,

因為如果遞歸了999層都沒有解決問題,那麽,你該想想是不是代碼寫的太爛了,呵呵……..

遞歸的特性

1、遞歸必須要有一個結束條件,否則就是一個死循環,直到報錯
2、每次進入更深一次遞歸時,遞歸的規模會比上次遞歸有所減小
3、遞歸的執行效率不高,遞歸層次過多會導致棧溢出

遞歸的作用

用於很多計算:斐波拉契數列,漢羅塔,多級評論樹,二分查找,階乘

二分查找例子

data_set = [1,3,4,6,7,8,9,10,11,13,14,16,18,19,21]
# data_set = list(range(101))


def b_search(n, low, high, d):
    mid = int((low + high) / 2)  # 中間值
    print(mid)
    if low == high:  # 第一位 和 最後一個 對比(索引的對比)
        print(not find)
        return
    if d[mid] > n:
        print(go left, low, high, d[mid])
        b_search(n, low, mid, d)
    if d[mid] < n:
        print(go right, low, high, d[mid])
        b_search(n, mid, high, d)
    else:
        print(find it, d[mid])  


b_search(16, 0, len(data_set), data_set)

尾遞歸

尾遞歸是對遞歸的優化,提高遞歸的效率,但是在python中並不支持,然並卵

優化:

在調用下次遞歸時,直接return自己,不保留外層函數的在內存中的數據,遞歸需要的只是這一層的信息,所以節省了內存,提高了效率

然而在python中,因為沒有優化,我們鼓勵使用叠代器來改寫尾遞歸

(引用自知乎)

python 之 遞歸