what's the python之遞歸函數、二分算法與漢諾塔遊戲

what's the 遞歸?

  遞歸函數的定義:在函數裏能夠再調用函數,若是這個調用的函數是函數自己,那麼就造成了一個遞歸函數。算法

  遞歸的最大深度爲997,這個是程序強制定義的,997徹底能夠知足通常狀況下用到遞歸的情形。數組

#最大997層
def foo(n): print(n) n += 1 foo(n) foo(1)

 

舉個栗子:ide

  假設你想知道A的年齡,但你只知道A比B大2歲,B又比C大兩歲,C又比D大兩歲,D比E大兩歲,剛好你知道E的歲數,那是否是就能知道A的歲數了呢,這就能夠組成一個遞歸。那咱們假設E的歲數是20函數

def age(n): if n == 1: return 20
    else: return age(n-1)+2

print(age(5))

 

遞歸小練習優化

def func1(x):
    print(x)
    func1(x-1)

def func2(x):
    if x>0:
        print(x)
        func2(x-1)

def func3(x):
    if x>0:
        func3(x-1)
        print(x)
        
func1(5)    #死循環
func2(5)    #5 4 3 2 1
func3(5)    #1 2 3 4 5
練習1
def test(n):
    if n == 0:
        print("個人小鯉魚", end='')
    else:
        print("抱着", end='')
        test(n-1)
        print("的我", end='')
def func(n):
    print('嚇得我抱起了', end='')
    test(n)

func(3)#嚇得我抱起了抱着抱着抱着個人小鯉魚的個人個人我
練習2(嚇得我抱起了抱着抱着抱着個人小鯉魚的個人個人我)

 

二分算法

  遞歸函數的一個經典用法就是二分算法,二分算法的意思是用對半切查找的方式從由一羣由小到大的數組成的列表中找到要找的數字的方法spa

舉個栗子:3d

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):                          def func(l, aim,start = 0,end = len(l)-1 ):                                 
    mid = (len(l)-1)//2                     mid = (start+end)//2
    if l:                                     if not l[start:end+1]:
        if aim > l[mid]:                       return
            func(l[mid+1:],aim)             elif aim > l[mid]:
        elif aim < l[mid]:                     return func(l,aim,mid+1,end)
            func(l[:mid],aim)               elif aim < l[mid]:
        elif aim == l[mid]:                   return func(l,aim,start,mid-1)
            print("bingo",mid)              elif aim == l[mid]:
    else:                                         print("bingo")
        print('找不到')                            return mid
func(l,66)                                index = func(l,68)
func(l,6)                                 print(index)

 

以上就是簡單的二分算法,固然由於切片會形成內存的損耗,因此咱們還能夠將以上代碼進行改進code

def bin_search_rec(data_set,value,low,high):
    if low <= high:
        mid=(low+high) // 2
        if data_set[mid] == value:
            return mid
        elif data_set[mid] > value:
            return bin_search_rec(data_set,value,low,mid-1)
        else:
            return bin_search_rec(data_set,value,mid+1,high)
    else:return None

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]
a=bin_search_rec(l,66,2,88) 
print(a)#2

 

漢諾塔遊戲

  漢諾塔遊戲是法國數學家愛德華·盧卡斯編寫的一個印度的古老傳說:大梵天創造世界的時候作了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。 大梵天命令婆羅門把圓盤從下面開始按大小順序從新擺放在另外一根柱子上。 在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。 64根柱子移動完畢之日,就是世界毀滅之時。blog

 

   這個遊戲能夠用遞歸的思想解決,首先咱們來捋一捋思路:遞歸

      兩個盤子時:

      1. 把小圓盤從A移動到B
      2. 把大圓盤從A移動到C
      3. 把小圓盤從B移動到C

      n個盤子時:

      1. 把n-1個圓盤(除去最後一個之外的全部)從A通過C移動到B
      2. 把第n個圓盤(最後一個)從A移動到C
      3. 把n-1個小圓盤從B通過A移動到C

 接下來咱們來寫代碼

a=0
def hanoi(n,x,y,z):
    global a
    if n==1:
        a+=1
        print(x,'-->',z)
    else:
        hanoi(n-1,x,z,y)#將前n-1個盤子從x移動到y上
        hanoi(1,x,y,z)#將最底下的最後一個盤子從x移動到z上
        hanoi(n-1,y,x,z)#將y上的n-1個盤子移動到z上

n=int(input('請輸入漢諾塔的層數:'))

hanoi(n,'柱子A','柱子B','柱子C')
print('一共用了%s次'%a)
"""
假設咱們的漢諾塔層數爲3
請輸入漢諾塔的層數:3
柱子A --> 柱子C
柱子A --> 柱子B
柱子C --> 柱子B
柱子A --> 柱子C
柱子B --> 柱子A
柱子B --> 柱子C
柱子A --> 柱子C
一共用了7次
"""

 

  漢諾塔移動次數的遞推式:h(x)=2h(x-1)+1。h(64)=18446744073709551615 假設婆羅門每秒鐘搬一個盤子,則總共須要5800億年!因此世界是不會毀滅的哇咔咔~

相關文章
相關標籤/搜索