斐波那契數(shù)列算法分析_第1頁(yè)
斐波那契數(shù)列算法分析_第2頁(yè)
斐波那契數(shù)列算法分析_第3頁(yè)
斐波那契數(shù)列算法分析_第4頁(yè)
斐波那契數(shù)列算法分析_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、斐波那契數(shù)列算法分析 斐波那契數(shù)列算法分析背景:假定你有一雄一雌一對(duì)剛出生的兔子,它們?cè)陂L(zhǎng)到一個(gè)月大小時(shí)開(kāi)始交配,在第二月結(jié)束時(shí),雌兔子產(chǎn)下另一對(duì)兔子,過(guò)了一個(gè)月后它們也開(kāi)始繁殖,如此這般持續(xù)下去。每只雌兔在開(kāi)始繁殖時(shí)每月都產(chǎn)下一對(duì)兔子,假定沒(méi)有兔子死亡,在一年后總共會(huì)有多少對(duì)兔子?在一月底,最初的一對(duì)兔子交配,但是還只有1對(duì)兔子;在二月底,雌兔產(chǎn)下一對(duì)兔子,共有2對(duì)兔子;在三月底,最老的雌兔產(chǎn)下第二對(duì)兔子,共有3對(duì)兔子;在四月底,最老的雌兔產(chǎn)下第三對(duì)兔子,兩個(gè)月前生的雌兔產(chǎn)下一對(duì)兔子,共有5對(duì)兔子;如此這般計(jì)算下去,兔子對(duì)數(shù)分別是:1, 1, 2, 3, 5, 8, 13, 21, 34,

2、55,89, 144, .看出規(guī)律了嗎?從第3個(gè)數(shù)目開(kāi)始,每個(gè)數(shù)目都是前面兩個(gè)數(shù)目之和。這就是著名的斐波那契(Fibonacci)數(shù)列。 有趣問(wèn)題:1,有一段樓梯有10級(jí)臺(tái)階,規(guī)定每一步只能跨一級(jí)或兩級(jí),要登上第10級(jí)臺(tái)階有幾種不同的走法?答:這就是一個(gè)斐波那契數(shù)列:登上第一級(jí)臺(tái)階有一種登法;登上兩級(jí)臺(tái)階,有兩種登法;登上三級(jí)臺(tái)階,有三種登法;登上四級(jí)臺(tái)階,有五種方法所以,1,2,3,5,8,13登上十級(jí),有89種。2,數(shù)列中相鄰兩項(xiàng)的前項(xiàng)比后項(xiàng)的極限是多少,就是問(wèn),當(dāng)n趨于無(wú)窮大時(shí),F(xiàn)(n)/F(n+1)的極限是多少?答:這個(gè)可由它的通項(xiàng)公式直接得到,極限是(-1+5)/2,這個(gè)就

3、是所謂的黃金分割點(diǎn),也是代表大自然的和諧的一個(gè)數(shù)字。  數(shù)學(xué)表示:Fibonacci數(shù)列的數(shù)學(xué)表達(dá)式就是:F(n) = F(n-1) + F(n-2)F(1) = 1F(2) = 1 遞歸程序1:Fibonacci數(shù)列可以用很直觀的二叉遞歸程序來(lái)寫,用C+語(yǔ)言的描述如下:long fib1(int n)if (n <= 2)return 1;elsereturn fib1(n-1) + fib1(n-2);看上去程序的遞歸使用很恰當(dāng),可是在用VC2005的環(huán)境下測(cè)試n=37的時(shí)候用了大約3s,而n=45的時(shí)候基本下樓打完飯也看不到結(jié)果顯然這種遞歸的效率太低了

4、!遞歸效率分析:例如,用下面一個(gè)測(cè)試函數(shù):long fib1(int n, int* arr)arrn+;if (n <= 2)return 1;elsereturn fib1(n-1, arr) + fib1(n-2, arr);這時(shí),可以得到每個(gè)fib(i)被計(jì)算的次數(shù):fib(10) = 1fib(9) = 1fib(8) = 2fib(7) = 3fib(6) = 5fib(5) = 8fib(4) = 13fib(3) = 21fib(2) = 34fib(1) = 55fib(0) = 34可見(jiàn),計(jì)算次數(shù)呈反向的Fibonacci數(shù)列,這顯然造成了大量重復(fù)計(jì)算。我們令T(N)

5、為函數(shù)fib(n)的運(yùn)行時(shí)間,當(dāng)N>=2的時(shí)候我們分析可知:T(N) = T(N-1) + T(N-2) + 2而fib(n) = fib(n-1) + fib(n-2),所以有T(N) >= fib(n),歸納法證明可得:fib(N) < (5/3)N當(dāng)N>4時(shí),fib(N)>= (3/2)N標(biāo)準(zhǔn)寫法:顯然這個(gè)O((3/2)N) 是以指數(shù)增長(zhǎng)的算法,基本上是最壞的情況。其實(shí),這違反了遞歸的一個(gè)規(guī)則:合成效益法則。合成效益法則(Compound interest rule):在求解一個(gè)問(wèn)題的同一實(shí)例的時(shí)候,切勿在不同的遞歸調(diào)用中做重復(fù)性的工作。所以在上面的代碼中調(diào)

6、用fib(N-1)的時(shí)候?qū)嶋H上同時(shí)計(jì)算了fib(N-2)。這種小的重復(fù)計(jì)算在遞歸過(guò)程中就會(huì)產(chǎn)生巨大的運(yùn)行時(shí)間。 遞歸程序2:用一叉遞歸程序就可以得到近似線性的效率,用C+語(yǔ)言的描述如下:long fib(int n, long a, long b, int count)if (count = n)return b;return fib(n, b, a+b, +count); long fib2(int n)return fib(n, 0, 1, 1);這種方法雖然是遞歸了,但是并不直觀,而且效率上相比下面的迭代循環(huán)并沒(méi)有優(yōu)勢(shì)。 迭代解法:Fibonacci數(shù)列用迭

7、代程序來(lái)寫也很容易,用C+語(yǔ)言的描述如下:/也可以用數(shù)組將每次計(jì)算的f(n)存儲(chǔ)下來(lái),用來(lái)下次計(jì)算用(空間換時(shí)間)long fib3 (int n)long x = 0, y = 1;for (int j = 1; j < n; j+)y = x + y;x = y - x;return y;這時(shí)程序的效率顯然為O(N),N = 45的時(shí)候<1s就能得到結(jié)果。 矩陣乘法:我們將數(shù)列寫成:Fibonacci0 = 0,F(xiàn)ibonacci1 = 1Fibonaccin = Fibonaccin-1 + Fibonaccin-2 (n >= 2)可以將它寫成矩陣乘法形式:

8、將右邊連續(xù)的展開(kāi)就得到:下面就是要用O(log(n)的算法計(jì)算:顯然用二分法來(lái)求,結(jié)合一些面向?qū)ο蟮母拍?,C+代碼如下:class Matrixpublic:long matr22; Matrix(const Matrix&rhs);Matrix(long a, long b, long c, long d);Matrix& operator=(const Matrix&);friend Matrix operator*(const Matrix& lhs, const Matrix& rhs)Matrix ret(0,0,0,0);ret.m

9、atr00 = lhs.matr00*rhs.matr00 + lhs.matr01*rhs.matr10;ret.matr01 = lhs.matr00*rhs.matr01 + lhs.matr01*rhs.matr11;ret.matr10 = lhs.matr10*rhs.matr00 + lhs.matr11*rhs.matr10;ret.matr11 = lhs.matr10*rhs.matr01 + lhs.matr11*rhs.matr11;return ret; Matrix:Matrix(long a, long b, long c, long d)this-&g

10、t;matr00 = a;this->matr01 = b;this->matr10 = c;this->matr11 = d; Matrix:Matrix(const Matrix &rhs)this->matr00 = rhs.matr00;this->matr01 = rhs.matr01;this->matr10 = rhs.matr10;this->matr11 = rhs.matr11; Matrix& Matrix:operator =(const Matrix &rhs)this->ma

11、tr00 = rhs.matr00;this->matr01 = rhs.matr01;this->matr10 = rhs.matr10;this->matr11 = rhs.matr11;return *this; Matrix power(const Matrix& m, int n)if (n = 1)return m;if (n%2 = 0)return power(m*m, n/2);elsereturn power(m*m, n/2) * m; long fib4 (int n)Matrix matrix0(1, 1, 1, 0);m

12、atrix0 = power(matrix0, n-1);return matrix0.matr00;這時(shí)程序的效率為O(log(N)) 。 公式解法:在O(1)的時(shí)間就能求得到F(n)了: 注意:其中x表示取距離x最近的整數(shù)。用C+寫的代碼如下:long fib5(int n)double z = sqrt(5.0);double x = (1 + z)/2;double y = (1 - z)/2;return (pow(x, n) - pow(y, n)/z + 0.5; 這個(gè)與數(shù)學(xué)庫(kù)實(shí)現(xiàn)開(kāi)方和乘方本身效率有關(guān)的,我想應(yīng)該還是在O(log(n)的效率。 總結(jié):上面給出

13、了5中求解斐波那契數(shù)列的方法,用測(cè)試程序主函數(shù)如下:int main()cout << fib1(45) << endl;cout << fib2(45) << endl;cout << fib3(45) << endl;cout << fib4(45) << endl;cout << fib5(45) << endl;return 0; 函數(shù)fib1會(huì)等待好久,其它的都能很快得出結(jié)果,并且相同為:1134903170。而后面兩種只有在n = 1000000000的時(shí)候會(huì)顯示

14、出優(yōu)勢(shì)。由于我的程序都沒(méi)有涉及到高精度,所以要是求大數(shù)據(jù)的話,可以通過(guò)取模來(lái)獲得結(jié)果的后4位來(lái)測(cè)試效率與正確性。另外斐波那契數(shù)列在實(shí)際工作中應(yīng)該用的很少,尤其是當(dāng)數(shù)據(jù)n很大的時(shí)候(例如:1000000000),所以綜合考慮基本普通的非遞歸O(n)方法就很好了,沒(méi)有必要用矩陣乘法。 附錄:程序全部源碼:#include <iostream>#include <vector>#include <string>#include <cmath>#include <fstream> using namespace std;&

15、#160;class Matrixpublic:long matr22; Matrix(const Matrix&rhs);Matrix(long a, long b, long c, long d);Matrix& operator=(const Matrix&);friend Matrix operator*(const Matrix& lhs, const Matrix& rhs)Matrix ret(0,0,0,0);ret.matr00 = lhs.matr00*rhs.matr00 + lhs.matr01*rhs.matr10;r

16、et.matr01 = lhs.matr00*rhs.matr01 + lhs.matr01*rhs.matr11;ret.matr10 = lhs.matr10*rhs.matr00 + lhs.matr11*rhs.matr10;ret.matr11 = lhs.matr10*rhs.matr01 + lhs.matr11*rhs.matr11;return ret; Matrix:Matrix(long a, long b, long c, long d)this->matr00 = a;this->matr01 = b;this->matr10 = c;th

17、is->matr11 = d; Matrix:Matrix(const Matrix &rhs)this->matr00 = rhs.matr00;this->matr01 = rhs.matr01;this->matr10 = rhs.matr10;this->matr11 = rhs.matr11; Matrix& Matrix:operator =(const Matrix &rhs)this->matr00 = rhs.matr00;this->matr01 = rhs.matr01;this->

18、;matr10 = rhs.matr10;this->matr11 = rhs.matr11;return *this; Matrix power(const Matrix& m, int n)if (n = 1)return m;if (n%2 = 0)return power(m*m, n/2);elsereturn power(m*m, n/2) * m; /普通遞歸long fib1(int n)if (n <= 2)return 1;elsereturn fib1(n-1) + fib1(n-2);/*上面的效率分析代碼long fib1(int n, int* arr)arrn+;if (n <= 1)return 1;elsereturn fib1(n-1, arr) + fib1(n-2, arr);*/ long fib(int n, long a, long b, int count)if (count = n)return b;return fib(n, b, a+b, +count);/一叉遞歸long

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論