遞迴,就是函式在執行的過程中呼叫自己。
**示例
def recursion(n):出現的效果就是,這個函式在不斷的呼叫自己,每次呼叫就n+1,相當於迴圈了。print(n)
recursion(n+1)
recursion(
1)
可是為何執行了900多次就出錯了呢?還說超過了最大遞迴深度限制,為什麼要限制呢?
通俗來講,是因為每個函式在呼叫自己的時候 還沒有退出,佔記憶體,多了肯定會導致記憶體崩潰。
本質上講呢,在計算機中,函式呼叫是通過棧(stack)這種資料結構實現的,每當進入乙個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位。
讓我們通過現象來看本質, 下面是是用遞迴寫的,讓10不斷除以2,直到0為止。
列印的是1, 然後最裡層的函式就結束了,結束後會返回到之前呼叫它的位置。即上一層,上一層列印的是2,再就是5,再就是10,即最外層函式,然後結束,總結,這個遞迴就是一層層進去,還要一層層出來。
通過上面的例子,我們可以總結遞迴幾個特點:
必須有乙個明確的結束條件,要不就會變成死迴圈了,最終撐爆系統
每次進入更深一層遞迴時,問題規模相比上次遞迴都應有所減少
遞迴執行效率不高,遞迴層次過多會導致棧溢位
可以用於解決很多演算法問題,把複雜的問題分成乙個個小問題,一一解決。
求階乘任何大於1的自然數n階乘表示方法:
n!=1×2×3×……×n
或 n!=n×(n-1)!
即舉例:4! = 4x3x2x1 = 24
用遞迴**來實現
def factorial(n):2分查詢if n == 0
: #是0的時候,就運算完了
return
1return n * factorial(n-1
) # 每次遞迴相乘,n值都較之前小1
d = factorial(4
)print(d)
在乙個已排序的陣列data_set中,使用二分查詢n,假如這個陣列的範圍是[low...high],我們要的n就在這個範圍裡。查詢的方法是拿low到high的正中間的值,我們假設是mid,來跟n相比,如果mid>n,說明我們要查詢的n在前陣列data_set的前半部,否則就在後半部。無論是在前半部還是後半部,將那部分再次折半查詢,重複這個過程,知道查詢到n值所在的地方。
data_set = list(range(101))def b_search(n,low,high,d):
mid = int((low+high)/2
) # 找到列表中間的值
if low ==high:
print(
"not find")
return
if d[mid] > n: # 列表中間值》n, 代數要找的資料在左邊
print(
"go left:
",low,high,d[mid])
b_search(n,low,mid,d) # 去左邊找
elif d[mid]
print(
"go right:
",low,high,d[mid])
b_search(n,mid+1
,high,d) # 去右邊找
else
: print(
"find it
", d[mid])
b_search(
188, 0,len(data_set),data_set)
go right: 0最多將會操作7次,其實因為每一次我們都拋掉當前確定的區間的一半的區間作為不可能解部分,那麼相當於求最多操作次數,就是在區間內,最多將有多少個一半可以拋去、那麼就是將100一直除以2,直到不能除為止。10150
go right:
51101
76go right:
77101
89go right:
90101
95go right:
96101
98go right:
99101
100not find
那麼這個運算過程,其實就是相當於求了乙個log2(100)≈7。
在講特性時,我們說遞迴效率不高,因為每遞迴一次,就多了一層棧,遞迴次數太多還會導致棧溢位,這也是為什麼python會預設限制遞迴次數的原因。但有一種方式是可以實現遞迴過程中不產生多層棧的,即尾遞迴,
尾遞迴在函式最尾部有return,return值是遞迴形式呼叫,且返回值與上一層函式無任何依賴。
尾遞迴例子
def calc(n):我們之前求的階乘是尾遞迴麼?print(n - 1
)
if n > -50
:
return calc(n-1)
def factorial(n):上面的這種遞迴計算最終的return操作是乘法操作。所以不是尾遞迴。因為每個活躍期的返回值都依賴於用n乘以下乙個活躍期的返回值,因此每次呼叫產生的棧幀將不得不儲存在棧上直到下乙個子呼叫的返回值確定。if n == 0
: #是0的時候,就運算完了
return
1return n * factorial(n-1
) # 每次遞迴相乘,n值都較之前小1
d = factorial(4
)print(d)
Python3 遞迴函式
1.必須有乙個明確的結束條件 2.每次進入更深一層遞迴時,問題規模相比上次遞迴都應有所減少 3.遞迴效率不高,遞迴層次過多會導致棧溢位 在計算機中,函式呼叫是通過棧 stack 這種資料結構實現的,每當進入乙個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,...
Python3 遞迴函式
在函式內部,可以呼叫其他函式。如果乙個函式在內部呼叫自身本身,這個函式就是遞迴函式。def calc n print n if int n 2 0 return n return calc int n 2 calc 10 輸出 105 21遞迴特性 1.必須有乙個明確的結束條件,最多遞迴999次 2...
Python3 遞迴函式
1 def fat n 2 result 13 for i in range 2,n 1 4 result result i5 return result6 print fat 5 7 8 9 def digui x 10 if x 1 11 return 112 return x digui x ...