今天在看乙個公開課的時候看到了斐波那契數列的演算法,忽然有了一點感想:不知道為什麼大家在給別人講這個數列的演算法的時候講的最多的就是遞迴的演算法,明明遞迴的演算法要比迭代的演算法執行時間長很多,堆疊開銷也要大很多,那為什麼不給他們講那種時間和空間開銷都很小的迭代演算法呢。
這是乙個想法又出現在我的腦子裡,迭代能比遞迴消耗多少時間和空間呢?答案我也不知道,當然我可以寫個程式來驗證一下,為什麼不呢。於是我寫了以下程式來檢測時間開銷:
在說程式**之前,我們要考慮用什麼來表示計算的時間呢?我的第一反應使用系統時間
time_t,它是定義在time.h中的乙個型別,表示乙個日曆時間,也就是從2023年1月1日0時0分0秒到此時的秒數,原型是:
typedef long time_t; /* time value */
可以看出time_t其實是乙個長整型,由於長整型能表示的數值有限,因此它能表示的最遲時間是2023年1月18日19時14分07秒。悲劇了,因為系統時間精確到秒,而現在計算機的主頻都很快,1秒鐘程式可能已經計算結束了,所以我們要找到另乙個方法來計算時間,這時
就要使用clock函式了,函式原型:
clock_t clock(void);
從定義可以看出clock返回乙個clock_t型別,這個型別也定義在time.h中,原型是:
typedef long clock_t;
clock_t也是乙個長整型,表示的是從程式開始執行到執行clock函式時所經過的cpu時鐘計時單元數。於是**就出來了:
#include
#include
using namespace std;
int fibonaccirecursion(int num);
int fibonacciiterator(int num);
int main()
int fibonaccirecursion(int num)
int fibonacciiterator(int num)
return first + second; }
非常有意思的是當時我想計算的是斐波那契數列的第10000個數值,呵呵,然後我就想當然的寫下了
value = fibonaccirecursion(10000); 結果悲劇了,很明顯我沒有考慮到整形的表示範圍是多少,我們可以簡單地計算以下,以32個bit為例,整形的最大表示範圍是:-2^31--(2^31-1),當然我們不知道這個數字是多少,但是可以簡單地認為2^10=1000。那麼也就是表示範圍大概是在-2,000,000,000到2000,000,000之間。而斐波那契數列我們可以簡單地表示為f(x)=2*f(x-1),當然這是不準確的,由於f(2)=2,我們可以簡單地表示f=2^(x-1
),也就是說f(32)可能就已經超出表示範圍了。
當然f(10000)是可以計算的,這個問題之後在考慮,那麼我們的計算結果是什麼呢:
遞迴使用時間7
迭代使用時間0
結果很明顯,迭代的時間使用的比遞迴使用的少的多。
遞迴與斐波那契數列
迭代實現 def fab n a1 1 a2 1 a3 1if n 1 print 輸入有誤 return 1 while n 2 0 a3 a1 a2 a1 a2 a2 a3 a 1return a3 result fab 20 if result 1 print 總共有 d對小兔子誕生 resu...
斐波那契數列,遞迴與迴圈
斐波那契數列 fibonacci sequence 又稱 分割數列 兔子數列,是數學家列昂納多 斐波那契於1202年提出的數列。斐波那契數列為1 1 2 3 5 8 13 21 34 此數列從第3項開始,每一項都等於前兩項之和,遞推公式為f n f n 1 f n 2 n 3,f 1 1,f 2 1...
斐波那契數列 遞迴與非遞迴
首先來說下遞迴,遞迴的思想是大事化小。斐波那契數列 1,1,2,3,5,8,13,21.設f n 是第n個斐波那契數,當n 2,斐波那契數都為1 當n 2,那麼第f n 個斐波那契數就等於前兩個斐波那契數之和。遞迴的 實現 includeint fbnq int n int main 輸入10,得到...