從兩種斐波那契數的實現認識遞迴演算法

2021-10-19 16:10:00 字數 3624 閱讀 4674

目錄

一、斐波那契數列定義

二、兩種遞迴實現方式及分析

1、方式一:使用數學公式直接實現(二分遞迴)第n個斐波那契數

2、方式二:使用線性遞迴計算第n個斐波那契數(推薦方式)

三、對遞迴的認識

四、其他概念

斐波那契數列(fibonacci sequence),又稱**分割數列,因數學家萊昂納多·斐波那契(leonardoda fibonacci)以兔子繁殖為例子而引入,故又稱為「兔子數列」,指的是這樣乙個數列:0、1、1、2、3、5、8、13、21、34、……這個數列從第3項開始,每一項都等於前兩項之和。在數學上,斐波那契數列以如下被以遞推的方法定義:f(0)=0,f(1)=1, f(n)=f(n - 1)+f(n - 2)(n ≥ 2,n ∈ n*)

根據斐波那契數列數學定義:

f(0)=0,f(1)=1, f(n)=f(n - 1)+f(n - 2)(n ≥ 2,n ∈ n*)

如下兩種使用遞迴計算斐波那契數列的方法(python3):

def fibonacci_1(n):

if n<=1:

return n

else:

return fibonacci_1(n-2)+fibonacci_1(n-1)

這種方式中,是基於數學定義直接實現,也是很簡便的實現方法,但是,需要關注的問題是,這種方式也會直接導致方法的執行效率會非常低,會隨著n越大,其效率也更低。計算第n個斐波那契數需要對該方法進行指數級別的呼叫。假設用cn表示第n個斐波那契數需要呼叫fibonacci_1(n)的次數,有如下:

第n個斐波那契數呼叫方法次數

n=0c0=1

n=1c1=1

n=2c2=c0+c1+1=3

n=3c3=c1+c2+1=5

n=4c4=c2+c3+1=9

n=5c5=c3+c4+1=15

n=6c6=c4+c5+1=25

n=7c7=c5+c6+1=41

n=8c8=c6+c7+1=67

n=9c9=c7+c8+1=109

如果一直按照這個方式進行下去,我們可以從上表中看出,n越大呼叫次數也越多,使得呼叫的總次數時n的指數級。

使用如下程式段計算50次(windows10 cpu 1c):

if __name__ == "__main__":

t1 = time.clock()

for i in range(50):

t11 = time.clock()

print("n={},fibonacci={}".format(i,fibonacci_1(i)))

t12 = time.clock()

print("cost time:{}".format(t12-t11))

t2 = time.clock()

print("sum time:{}".format(t2-t1))

擷取了部分結果:n=31時,花費時間0.4s,但是當n=41時,需要時間52s,這樣看來n越大,效率是很低的。

n=31,fibonacci=1346269

cost time:0.43121010000000004

n=32,fibonacci=2178309

cost time:0.714747

n=33,fibonacci=3524578

cost time:1.3300094999999998

n=34,fibonacci=5702887

cost time:1.7607852999999998

n=35,fibonacci=9227465

cost time:2.8848124000000004

n=36,fibonacci=14930352

cost time:4.900053

n=37,fibonacci=24157817

cost time:7.670326699999999

n=38,fibonacci=39088169

cost time:13.099861399999998

n=39,fibonacci=63245986

cost time:20.710187599999998

n=40,fibonacci=102334155

cost time:32.3978941

n=41,fibonacci=165580141

cost time:52.244939900000006

def fibonacci_2(n):

if n<=1:

return (n,0)

else:

(a,b) = fibonacci_2(n-1)

return (a+b,a)

方式二每次只呼叫fibonacci_2方法一次,該方法每次返回一對連續的斐波拉契數列,而不是返回乙個斐波那契數,在o(n)時間內完成整體計算。

同樣計算50次,擷取了部分結果如下:每次花費的時間都非常小,總共的時間也在1秒以內。

n=32,cost time:7.000000000000062e-06

n=33,cost time:7.299999999994811e-06

n=34,cost time:7.699999999999374e-06

n=35,cost time:7.900000000005125e-06

n=36,cost time:8.100000000003937e-06

n=37,cost time:8.099999999996998e-06

n=38,cost time:8.399999999998686e-06

n=39,cost time:8.500000000001562e-06

n=40,cost time:8.79999999999631e-06

n=41,cost time:8.899999999999186e-06

n=42,cost time:9.200000000000874e-06

n=43,cost time:9.500000000002562e-06

n=44,cost time:9.699999999994435e-06

n=45,cost time:9.80000000000425e-06

n=46,cost time:1.0200000000001874e-05

n=47,cost time:1.0599999999999499e-05

n=48,cost time:1.0700000000002374e-05

n=49,cost time:1.0999999999997123e-05

使用遞迴時,就效率而言,效率低的遞迴和效率高的遞迴,就如同白天和黑夜,差別懸殊。對於乙個實際問題,對於遞迴演算法的設計顯得尤為重要。另乙個需要注意的問題是在遞迴誤用,避免出現無限遞迴,會很快耗盡計算機資源,不僅僅是cpu的使用,也會因連續不斷的呼叫建立需要的記憶體資源。

1、線性遞迴

每個呼叫中至多執行呼叫乙個新的遞迴呼叫

2、二路遞迴

乙個遞迴函式執行呼叫兩個遞迴函式時,稱為二路遞迴

3、多重遞迴

乙個遞迴函式執行呼叫三個或三個以上遞迴函式時,稱為多重遞迴

迴圈斐波那契數列 斐波那契數列的兩種實現

最先研究這個數列的人是義大利人斐波那契,leonardo fibonacci,他在描述兔子生長的數目時用上了這數列 每個月兔子的總對數,就是這樣乙個序列 1,1,2,3,5,8,13,21.這個序列從第三項開始,每一項都等於前兩項之和。在數學上,斐波那契數列是以遞迴的方法來定義 f 1 1 f 2 ...

php 兩種方式實現求 斐波那契數 遞迴,遞推

斐波那契數,亦稱之為斐波那契數列 義大利語 successione di fibonacci 又稱 分割數列 費波那西數列 費波拿契數 費氏數列,指的是這樣乙個數列 1 1 2 3 5 8 13 21 在數學上,斐波那契數列以如下被以遞迴的方法定義 f 0 0,f 1 1,fn f n 1 f n ...

斐波那契數列 的兩種實現方式

一 先要回答乙個問題 什麼是婓波那契數列?答案在這裡 二 看 1 第一方法 遞迴實現 public static void main string args public static int fibonacci int i else if i 1 return fibonacci i 2 fibo...