1. 程式人生 > >遞歸函數與二分法

遞歸函數與二分法

elif 如果 rip erro wid port set error bin

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

遞歸的定義——在一個函數裏再調用這個函數本身
現在我們已經大概知道剛剛講的story函數做了什麽,就是在一個函數裏再調用這個函數本身,這種魔性的使用函數的方式就叫做遞歸。

遞歸的最大深度——997
正如你們剛剛看到的,遞歸函數如果不受到外力的阻止會一直執行下去。但是我們之前已經說過關於函數調用的問題,每一次函數調用都會產生一個屬於它自己的名稱空間,如果一直調用下去,就會造成名稱空間占用太多內存的問題,於是python為了杜絕此類現象,強制的將遞歸層數控制在了997(只要997!你買不了吃虧,買不了上當...).

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

    try:
        story(n)
    except RecursionError:
        print(n)
        exit()
		
story(1)

由此我們可以看出,未報錯之前能看到的最大數字就是997.當然了,997是python為了我們程序的內存優化所設定的一個默認值,我們當然還可以通過一些手段去修改它: 

import sys
print(sys.setrecursionlimit(100000))
我們可以通過這種方式來修改遞歸的最大深度,剛剛我們將python允許的遞歸深度設置為了10w,至於實際可以達到的深度就取決於計算機的性能了

遞歸函數與三級菜單

menu = {
    ‘北京‘: {
        ‘海澱‘: {
            ‘五道口‘: {
                ‘soho‘: {},
                ‘網易‘: {},
                ‘google‘: {}
            },
            ‘中關村‘: {
                ‘愛奇藝‘: {},
                ‘汽車之家‘: {},
                ‘youku‘: {},
            },
            ‘上地‘: {
                ‘百度‘: {},
            },
        },
        ‘昌平‘: {
            ‘沙河‘: {
                ‘老男孩‘: {},
                ‘北航‘: {},
            },
            ‘天通苑‘: {},
            ‘回龍觀‘: {},
        },
        ‘朝陽‘: {},
        ‘東城‘: {},
    },
    ‘上海‘: {
        ‘閔行‘: {
            "人民廣場": {
                ‘炸雞店‘: {}
            }
        },
        ‘閘北‘: {
            ‘火車戰‘: {
                ‘攜程‘: {}
            }
        },
        ‘浦東‘: {},
    },
    ‘山東‘: {},
}
def threeLM(dic):
    while True:
        for k in dic:print(k)
        key = input(‘input>>‘).strip()
        if key == ‘b‘ or key == ‘q‘:return key
        elif key in dic.keys() and dic[key]:
            ret = threeLM(dic[key])
            if ret == ‘q‘: return ‘q‘

threeLM(menu)

 

二分查找算法

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]
你觀察這個列表,這是不是一個從小到大排序的有序列表呀?

如果這樣,假如我要找的數比列表中間的數還大,是不是我直接在列表的後半邊找就行了?

技術分享圖片

這就是二分查找算法!

那麽落實到代碼上我們應該怎麽實現呢?

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 func(l,aim):
    mid = (len(l)-1)//2
    if l:
        if aim > l[mid]:
            func(l[mid+1:],aim)
        elif aim < l[mid]:
            func(l[:mid],aim)
        elif aim == l[mid]:
            print("bingo",mid)
    else:
        print(‘找不到‘)
func(l,66)
func(l,6)

升級版二分法
def search(num,l,start=0,end=0):
    start = start if start else 0
    end = end if end else len(l) - 1
    mid = (end - start)//2 + start
    if start > end:
        return None
    elif l[mid] > num :
        return search(num,l,start,mid-1)
    elif l[mid] < num:
        return search(num,l,mid+1,end)
    elif l[mid] == num:
        return mid

search(0,l)

  

遞歸函數與二分法