九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
青少年P(guān)ython編程系列28:Python中函數(shù)的遞歸調(diào)用

前面我們已經(jīng)講了Python中的函數(shù)的用法和屬性,本節(jié)課是函數(shù)部分的最后一講,主要講函數(shù)一個(gè)非常重要的“魔法”,這個(gè)“魔法”能夠解決很多比較難的問(wèn)題,“魔法”的名字叫遞歸。這節(jié)課我們一起了解一下遞歸吧。

一、遞歸的概念和作用

如果一個(gè)函數(shù)在內(nèi)部調(diào)用它本身,這個(gè)函數(shù)就是遞歸函數(shù)。遞歸函數(shù)通常會(huì)利用分支結(jié)構(gòu),其包含兩個(gè)部分:遞歸條件基線條件

遞歸條件是指什么情況下函數(shù)會(huì)調(diào)用本身;基線條件是指遞歸的終止條件。

遞歸是程序設(shè)計(jì)中的一個(gè)重要方法,它使許多復(fù)雜的問(wèn)題變得簡(jiǎn)單,容易解決了。

遞歸是一種通過(guò)將大問(wèn)題分解為小規(guī)模同類子問(wèn)題進(jìn)而解決問(wèn)題的方法。它的核心思想是分治策略。分治,即“分而治之”,把一個(gè)復(fù)雜問(wèn)題分成兩個(gè)或更多相同的或者相似的子問(wèn)題,直到最后子問(wèn)題可以簡(jiǎn)單地被直接求解,原問(wèn)題的解也就是子問(wèn)題解的合并。

下面我們使用一個(gè)實(shí)例了解一下遞歸是怎樣寫(xiě)的。

二、使用遞歸計(jì)算階乘

階乘是數(shù)學(xué)上的一種運(yùn)算,它的定義為:一個(gè)正整數(shù)的階乘是所有小于及等于該數(shù)的正整數(shù)的積:

  • 1! = 1

  • 2! = 2 × 1

  • 3! = 3 × 2 × 1

  • 4! = 4 × 3 × 2 × 1

  • ……

我們通過(guò)觀察可以發(fā)現(xiàn),4! = 4 × 3!、3! = 3 × 2!。即n! = n × (n - 1)!

如果我們定義一個(gè)函數(shù)f(n)用來(lái)計(jì)算階乘,可以將它分解為求解n×f(n-1)。f(n-1)再分解為(n-1)×f(n-2)……以此類推。根據(jù)函數(shù)的定義,1的階乘即為1,最小的子問(wèn)題被解決,原問(wèn)題f(n)即為這些子問(wèn)題的合并。

根據(jù)這樣的思路,我們?cè)诤瘮?shù)f(n)中規(guī)定f(1) = 1,其他情況下返回n * f(n-1)即可。代碼如下:

def f(n): if n == 1: return 1 else: return n * f(n-1)print(f(5))

三、使用遞歸計(jì)算斐波拉契數(shù)列

斐波拉契數(shù)列也叫“黃金分割數(shù)列”,數(shù)列從0和1開(kāi)始,從第三項(xiàng)起,每一項(xiàng)都等于前兩項(xiàng)之和。數(shù)列的前n項(xiàng)包括:0,1,1,2,3,5,8,13,21,…。在數(shù)學(xué)上,斐波拉契數(shù)列以遞歸的方法來(lái)定義:

根據(jù)斐波拉契數(shù)列的數(shù)學(xué)定義,可使用遞歸算法計(jì)算該數(shù)列。代碼如下:

# 定義函數(shù)求斐波拉契數(shù)列的第n項(xiàng)def fibonacci(n):    if n == 0:        return 0    elif n == 1:        return 1    else:        return fibonacci(n-2) + fibonacci(n-1)# 打印斐波拉契數(shù)列的第0項(xiàng)到第10項(xiàng)for i in range(11):    print(fibonacci(i))

三、使用遞歸求解漢諾塔

漢諾塔(Hanoi Tower)是根據(jù)印度傳說(shuō)形成的數(shù)學(xué)問(wèn)題。有A、B、C三根柱子,A柱子上有n個(gè)圓盤,圓盤從下往上一次變小。要求按照下列規(guī)則將所有圓盤移動(dòng)到C柱子上,最終圓盤在C柱子上也按照從上而下依次變小的規(guī)律排列。問(wèn):至少移動(dòng)多少次才能移走所有圓盤?

移動(dòng)到過(guò)程中要求小圓盤必須在大圓盤上面,這個(gè)問(wèn)題我們可以找規(guī)律。如果只有1個(gè)圓盤,很明顯,我們把圓盤從A移動(dòng)到C;如果有2個(gè)圓盤,我們把小圓盤從A移動(dòng)到B,大圓盤從A移動(dòng)到C,在把小圓盤從B移動(dòng)到C……

以此類推,我們可以總結(jié)出來(lái),如果有n個(gè)圓盤,我們先把前面n-1個(gè)圓盤從A移動(dòng)到B,再把第n個(gè)圓盤移動(dòng)到C,最后把前面n-1個(gè)圓盤從B移動(dòng)到C。那么,上面的n-1個(gè)圓盤如何移動(dòng)呢?先把上面第n-2個(gè)移動(dòng)到B,把n-1個(gè)移動(dòng)到C,再把上面的n-2個(gè)移動(dòng)到C。這樣,正好符合遞歸的思想。代碼如下:

# 定義漢諾塔移法的函數(shù)def hanoi(n, a, b, c): # n為漢諾塔層數(shù),a、b、c為三根柱子 if n == 1: print(a, '-->', c) else: hanoi(n-1, a, c, b) print(a, '-->', c) hanoi(n-1, b, a, c)# 求解4層漢諾塔的移動(dòng)步驟hanoi(4, 'A', 'B', 'C')

四、使用遞歸繪制二叉樹(shù)

使用turtle畫(huà)出如圖所示的二叉樹(shù)
編程實(shí)現(xiàn):
1) 樹(shù)木主干向上生長(zhǎng),長(zhǎng)度為100;
2) 分形層數(shù)為4,二叉樹(shù);
3) 第一層樹(shù)枝長(zhǎng)度為60,逐層減小6;
4) 左右樹(shù)枝的傾斜角度為30°;
5) 樹(shù)木的顏色為棕色。

我們對(duì)圖片進(jìn)行分析:除了樹(shù)干外,每一級(jí)的樹(shù)枝都有如下規(guī)律: ① 畫(huà)左側(cè)樹(shù)枝 ②返回 ③畫(huà)右側(cè)樹(shù)枝 ④返回。

畫(huà)到末梢的時(shí)候如果長(zhǎng)度足夠,就繼續(xù)畫(huà)下一級(jí)的樹(shù)枝;如果長(zhǎng)度不夠,則結(jié)束。因此,這個(gè)程序我們可以使用遞歸實(shí)現(xiàn),代碼如下:

import turtle as tdef binary_tree(n):    if n <= 60 - 4 * 6: # 樹(shù)枝共有4層,每層長(zhǎng)度6,畫(huà)完結(jié)束        pass    else:        t.left(30) #從中間位置向左轉(zhuǎn)30°        t.forward(n) # 畫(huà)左側(cè)樹(shù)枝        binary_tree(n-6) # 畫(huà)下一層二叉樹(shù)        t.backward(n) # 畫(huà)完返回        t.right(60) #從左側(cè)30°轉(zhuǎn)到右側(cè)30°,共60°        t.forward(n)  # 畫(huà)左側(cè)樹(shù)枝        binary_tree(n-6)  # 畫(huà)下一層二叉樹(shù)        t.backward(n)  # 畫(huà)完返回        t.left(30) # 轉(zhuǎn)回中間位置t.setheading(90) # 設(shè)置畫(huà)筆方向?yàn)橄蛏蟭.pencolor('brown')t.forward(100) # 畫(huà)樹(shù)干binary_tree(60) #繪制二叉樹(shù)t.hideturtle()t.done()

五、使用遞歸計(jì)算全排列

從n個(gè)不同元素中任取m(m≤n)個(gè)元素,按照一定的順序排列起來(lái),叫做從n個(gè)不同元素中取出m個(gè)元素的一個(gè)排列。當(dāng)m=n時(shí)所有的排列情況叫全排列。

比如:[1,2,3]的全排列為:
[1,2,3]、[1,3,2]、[2,1,3]、[2,3,1]、[3,2,1]、[3,1,2]

我們?cè)偈褂?個(gè)數(shù)為例子找一下尋找全排列的規(guī)律:

(1)首先保持1不變,對(duì)2,3,4全排列;
(2)保持2不變,對(duì)3,4全排列;
(3)保持3不變,對(duì)4全排列,4的排列只有一種。得到1,2,3,4
(4)然后3不能不變了,繼續(xù)保持2不變,3,4互換得到1,2,4,3
(5)以1,2打頭的排列完成,接下來(lái)把3換到2的位置,繼續(xù)(3)、(4)的操作

如果有n個(gè)數(shù)的列表進(jìn)行全排列,我們定義perm(list,0,n)函數(shù):

取出第一個(gè)元素放到最后,即a[1]與a[n]交換,然后遞歸求a[n-1]的全排列

1)如果只有一個(gè)元素n=1,a=[1]則全排列就是[1]

2)如果有兩個(gè)元素n=2,a=[1,2] 則全排列是:
[2,1] -- a[1]與a[2]交換。交換后求a[2-1]=[2]的全排列,歸結(jié)到1)
[1,2] -- a[2]與a[2]交換。交換后求a[2-1]=[1]的全排列,歸結(jié)到1)

3)如果有三個(gè)元素n=3,a={1,2,3} 則全排列是
[[2,3],1] -- a[1]與a[3]交換。后求a[3-1]=[2,3]的全排列,歸結(jié)到2)
[[1,3],2] -- a[2]與a[3]交換。后求a[3-1]=[1,3]的全排列,歸結(jié)到2)
[[1,2],3] -- a[3]與a[3]交換。后求a[3-1]=[1,2]的全排列,歸結(jié)到2)

具體的代碼如下所示:

count = 0 #統(tǒng)計(jì)全排列的個(gè)數(shù)def permutation(n, begin, end): if begin >= end: global count count += 1 print(n) else: i = begin for num in range(begin, end): n[num], n[i] = n[i], n[num] permutation(n, begin+1, end) n[num], n[i] = n[i], n[num]n = [1, 2, 3, 4]permutation(n, 0, len(n))print(count)

六、函數(shù)遞歸調(diào)用的優(yōu)點(diǎn)和缺點(diǎn)

遞歸優(yōu)點(diǎn):

  1. 代碼可讀性高,程序簡(jiǎn)潔

  2. 在解決特殊問(wèn)題如二叉樹(shù)問(wèn)題,漢諾塔問(wèn)題是有著自己天然的優(yōu)勢(shì)

遞歸缺點(diǎn):

  1. 遞歸由于是函數(shù)調(diào)用自身,而函數(shù)調(diào)用是有時(shí)間和空間的消耗的:每一次函數(shù)調(diào)用,都需要在內(nèi)存棧中分配空間以保存參數(shù)、返回地址以及臨時(shí)變量,而往棧中壓入數(shù)據(jù)和彈出數(shù)據(jù)都需要時(shí)間。

  2. 遞歸中很多計(jì)算都是重復(fù)的,由于其本質(zhì)是把一個(gè)問(wèn)題分解成兩個(gè)或者多個(gè)小問(wèn)題,多個(gè)小問(wèn)題存在相互重疊的部分,則存在重復(fù)計(jì)算,如斐波那契數(shù)列的遞歸實(shí)現(xiàn)。

  3. 調(diào)用??赡軙?huì)溢出,其實(shí)每一次函數(shù)調(diào)用會(huì)在內(nèi)存棧中分配空間,而每個(gè)進(jìn)程的棧的容量是有限的,當(dāng)調(diào)用的層次太多時(shí),就會(huì)超出棧的容量,從而導(dǎo)致棧溢出。

七、課后思考題

1、編程題

使用遞歸的方式計(jì)算1+2+3+……+99+100的和

2、編程題

繪制一個(gè)如圖所示的三叉樹(shù)

1) 樹(shù)木主干向上生長(zhǎng),長(zhǎng)度為100;

2) 分形層數(shù)為3,三叉樹(shù);

3) 第一層樹(shù)枝長(zhǎng)度為60,逐層減小10;

4) 第一層每?jī)筛鶚?shù)枝夾角50°,逐層減半;

5) 樹(shù)木的顏色為綠色。

 

八、上節(jié)課思考題答案

1、D

2、對(duì)

3、參考代碼:

import mathdef avg(*args, **kwargs):    a = sum(args) / len(args)    key = kwargs.get('appr')    if key == 'floor':        a = math.floor(a)    elif key == 'ceil':        a = math.ceil(a)    else:        a = int(round(a))    return aprint(avg(2,3,4,5,6,22,3,4,5))print(avg(2,3,4,5,6,22,3,4,5,appr='floor'))print(avg(2,3,4,5,6,22,3,4,5,appr='ceil'))

4、參考代碼:

def ishealthy(height, weight, gender='male'): bmi = weight / height ** 2 healthy = False if gender == 'male': if bmi >= 20 and bmi <= 25: healthy = True elif gender == 'female': if bmi >= 18 and bmi <= 23: healthy = True else: healthy = None # 如果性別輸入的既不是男也不是女,則不返回結(jié)果 return healthyprint(ishealthy(1.7, 70))print(ishealthy(1.62, 50, 'female'))
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Python遞歸函數(shù)計(jì)算階乘n!
Python|用python解決階乘問(wèn)題
什么是遞歸函數(shù)?
遞歸算法
遞歸算法——階乘、斐波那契數(shù)列_使用遞歸
python筆記
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服