python_fullstack基礎(十)-遞歸函數

遞歸函數

一、定義

在函數中調用自身函數,就稱改函數爲遞歸函數

二、遞歸的特點

1、python從內存角度出發做了限制,遞歸的大遞歸深度默認是997/998

  • 可以手動修改python參數來改變該限制
# import sys
# sys.setrecursionlimit(max_recursion)

2、遞歸的優缺點

  • 遞歸的缺點 : 佔內存
  • 遞歸的優點: 會讓代碼變簡單

三、初識遞歸

# 需求

# A 年齡多大?       
# A 比 B 大兩歲
# B 年齡多大?      
# B 比 C 大兩歲
# C 年齡多大?       
# C 比 D 大兩歲
# D 年齡多大?
# D今年40歲

# 分析:

A ——>  n = 4   age(4) = age(3)+2 = age(n-1) + 2
B ——>  n = 3   age(3) = age(2) + 2 = age(n-1) +2
C ——>  n = 2   age(2) = age(1) + 2 = age(n-1) +2
D ——>  n = 1   age(1) = 40

# 代碼實現

def find_age(n):
    if n == 1:
        return 40
    else:
        return find_age(n-1)+2

print(find_age(4))
>>> 46

# 代碼分解

# 第一次傳輸參數n = 4
def find_age(4):
    if 4 == 1:  # False
        return 40
    else:
        return find_age(4-1)+2 # ==> find_age(3)+2

# 第一次傳輸參數n = 3
def find_age(3):
    if 3 == 1:  # False
        return 40
    else:
        return find_age(3-1)+2 # ==> find_age(2)+2

# 第一次傳輸參數n = 2
def find_age(2):
    if 2 == 1:  # False
        return 40
    else:
        return find_age(2-1)+2 # ==> find_age(1)+2

# 第一次傳輸參數n = 1
def find_age(2):
    if 1 == 1:  # True
        return 40
    else:
        return find_age(n-1)+2

# 最終返回值的走向:
return find_age(1)+2 ===> 40+2 = 42
return find_age(2)+2 ===> 42+2 = 44
return find_age(3)+2 ===> 44+2 = 46

四、遞歸進階——二分法查找

1、二分法查找(折半搜索法)原理

折半搜索是一種在有序數組中查找某一特定元素的搜索算法。搜素過程從數組的中間元素開始,如果中間元素正好是要查找的元素,則搜素過程結束;如果某一特定元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半中查找,而且跟開始一樣從中間元素開始比較。這種搜索算法每一次比較都使搜索範圍縮小一半。

2、簡單二分法查找實現

# 該方法可以基本實現查找,但是有個問題就是lst的值會隨着遞歸的執行而改變,所以無法得到查找值所在原列表中的索引值

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

def simple_binary_search(lst,target):
    mid_index = len(lst)//2
    if lst:
        if lst[mid_index] > target:
            return simple_binary_search(lst[:mid_index],target)
        elif lst[mid_index] < target:
            return simple_binary_search(lst[mid_index+1:],target)
        elif lst[mid_index] == target:
            return ('找到了!所查找的值爲:{}'.format(lst[mid_index]))
        else:
            return ('對不起,沒有您要查找的值!')

print(simple_binary_search(l,66))

3、升級版二分法查找實現

# 該方法解決了簡單二分法查找中不能得到目標數在原列表中的索引問題,解決方式是每次不改變傳入的列表,而是將索引進行改變,從而達到縮減搜索列表長度的目的

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

def senior_binary_search(lst,target,start=None,end=None):
    start = 0 if start is None else start
    end = len(lst) if end is None else end
    mid_index = start + (end - start)//2
    if lst:
        if lst[mid_index] > target:
            return senior_binary_search(lst,target,start,mid_index-1)
        elif lst[mid_index] < target:
            return senior_binary_search(lst,target,mid_index+1,end)
        elif lst[mid_index] == target:
            return ('找到了!所查找的值爲:{},所在索引爲:{}'.format(lst[mid_index],mid_index))
        else:
            return ('對不起,沒有您要查找的值!')

print(senior_binary_search(l,66))

五、遞歸擴展

# 1、 斐波那契 —— 問第n個斐波那契數是多少?
def fibonacci(n):
    if n == 0 or n == 1:
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)


print(fibonacci(0))
print(fibonacci(1))
print(fibonacci(2))
>>> 1
>>> 1
>>> 2
# 階乘 n!
def factorial(n):
    if n == 0:
        return 1
    else:
        return factorial(n-1)*n

print(factorial(0))
print(factorial(1))
print(factorial(2))
print(factorial(3))

>>> 1
>>> 1
>>> 2
>>> 6
# 多級菜單——遞歸
menu = {
    '黑龍江省': {
             '哈爾濱市': {
                      '松北區': {},
                      '道里區': {},
                      '南崗區': {},
                      '香坊區': {}
                      },
             '齊齊哈爾市': {
                       '龍沙區': {},
                       '建華區': {},
                       '鐵鋒區': {},
                       },
             '牡丹江市': {
                      '愛民區': {},
                      '東安區': {},
                      '陽明區': {},
                      }
             },
    '吉林省': {
            '長春市': {
                    '南關區': {},
                    '寬城區': {},
                    '二道區': {},
                    },
            '吉林市': {
                    '船營區': {},
                    '昌邑區': {},
                    }
            },
    '遼寧省': {
            '瀋陽市': {
                    '瀋河區': {},
                    '和平區': {},
                    '皇姑區': {},
                    },
            '大連市': {
                    '西崗區': {},
                    '中山區': {},
                    }
            }
}

def recursion(dic):
    while True:
        for k in dic:
            print(k)
        user_input = input('輸入內容(輸入Q或q退出,輸入B或b返回上一級):\n>>>').strip()
        if user_input.lower() == 'b' or user_input.lower() == 'q':
            return user_input
        elif user_input in dic.keys() and dic[user_input]:
            res = recursion(dic[user_input])
            if res == 'q':
                return 'q'
        elif (not dic.get(user_input)) or (not dic[user_input]) :
            continue

recursion(menu)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章