標籤:部分 top idt strong case def == 程式 getting
遞迴執行個體:在盒子中尋找鑰匙
方法1:使用while迴圈演算法
(1) 建立一個要尋找的盒子堆。
(2) 從盒子堆取出一個盒子,在裡面找。
(3) 如果找到的是盒子,就將其加入盒子堆中,以便以後再尋找。
(4) 如果找到鑰匙,則大功告成!
(5) 回到第二步。
代碼
def look_for_key(main_box): pile=main_box.make_a_pile_to_look_through() while pile is not empty: box=pile.grap_a_box for item in box: if item.is_a_box(): pile.append(item) elif item.is_a_key(): print(‘found a key‘)
方法2:使用遞迴演算法
(1) 檢查盒子中的每樣東西。
(2) 如果是盒子,就回到第一步。
(3) 如果是鑰匙,就大功告成!
代碼
def look_for_key(box): for item in box: if item.is_a_box(): look_for_key(item) #遞迴 elif item.is_a_key(): print(‘found a key‘)
如果使用迴圈,程式的效能可能更高;如果使用遞迴,程式可能更容易理解。如何選擇要看什麼對你來說更重要。
基準條件和遞迴條件
編寫遞迴函式時,必須告訴它何時停止遞迴。否則會導致無限迴圈。
遞迴函式兩部分
基準條件(base case)和遞迴條件(recursive case)
遞迴條件:指的是函數調用自己基準條件:指的是函數不再調用自己,從而避免形成無限迴圈。
樣本
def countdown(i): print(i) if i<=0: #基準條件 return else: #遞迴條件 countdown(i-1) print(countdown(4))
棧定義
棧(stack)又名堆棧,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。
特點
LIFO,即後進先出(Last in, first out)
調用棧(call stack)
電腦在內部使用被稱為調用棧的棧。
樣本
def greet2(name): print("how are you," + name + "?")def bye(): print(‘ok bye!‘) def greet(name): print(‘hello,‘+name+‘!‘) greet2(name) print(‘getting ready to say bye..‘) bye()print(greet(‘lilip‘))
調用過程
- 調用greet(‘lilip’),首先為該函數調用分配一塊記憶體
- 列印,hello,lilip!
- 調用greet2(‘lilip’),接著為這個函數調用分配一塊記憶體
- 電腦使用一個棧表示這些記憶體塊,其中第二個記憶體塊位於第一個記憶體塊的上面。
- 列印,how are you,lilip?greet2函數運行完畢,然後從函數調用返回。此時,棧頂的記憶體塊被彈出。
- 棧頂記憶體塊是函數greet,返回到函數greet。
- 列印getting ready to say bye..
- 調用bye()函數,棧頂添加函數bye的記憶體塊
- 列印,ok bye!並從這個函數返回。
- 返回到函數greet,此時運行完畢。從函數greet返回,
調用另一個函數時,當前函數暫停並處於未完成狀態。該函數的所有變數的值都還在記憶體中
這個棧用於儲存多個函數的變數,被稱為調用棧。
遞迴調用棧
遞迴函式也使用調用棧!
樣本
階乘遞迴函式
def fact(x): if x==1: return 1 else: return x*fact(x-1) print(fact(3))
調用過程
代碼 |
調用棧 |
備忘 |
fact(3) |
|
第一次調用fact x=3 |
if x==1: |
|
|
else: |
|
|
return x*fact(x-1) |
|
遞迴調用 |
if x==1: |
|
現在位於對fact的第二次調用中 x=2 最上面的函數調用是當前所處的調用 |
else: |
|
兩個函數調用都有變數x,但這些x變數的值不同 |
return x*fact(x-1) |
fact |
x |
1 |
fact |
x |
2 |
fact |
x |
3 |
|
在棧頂層調用中,不能訪問下面其他記憶體塊調用的x變數,反之亦然 |
if x==1: |
fact |
x |
1 |
fact |
x |
2 |
fact |
x |
3 |
|
|
return 1 |
fact |
x |
1 |
fact |
x |
2 |
fact |
x |
3 |
|
從棧中彈出第一個方塊,意味著將從這個調用返回,返回1 |
return x*fact(x-1) |
|
x為2 fact(x-1)返回1 最終返回2 |
return x*fact(x-1) |
|
x為3 fact(x-1)返回2 最終返回6 |
注意:
- 每個fact調用都有自己的x變數。在一個函數調用中不能訪問另一個的x變數。
- 每個函數調用都要佔用一定的記憶體,如果棧很高,就意味著電腦儲存了大量函數調用的資訊。
小結
- 遞迴指的是調用自己的函數。
- 每個遞迴函式都有兩個條件:基準條件和遞迴條件。
- 棧有兩種操作:壓入和彈出。
- 所有函數調用都進入調用棧。
- 調用棧可能很長,這將佔用大量的記憶體。
【演算法】遞迴