fibonacci數列:
描寫了動物滋生數量、植物花序改變等大措施則。作為乙個經典的數學識題,fibonacci數列常作為例子展目前途序設計、資料構造與演算法等多個相干學科中。
下面容易地分析一下常見的fibonacci數列求解演算法。
1、遞迴法。大多數教材在解說遞迴演算法時總迷戀以fibonacci數列為例,這是因為我們能夠直觀地從定義公式的第三行看出fibonacci數列的遞迴性。其c++告終如下:
unsigned long fib(int n)遞迴演算法與定義公式極其合乎,草帶會意,但計算過程存在許多重複的計算,工夫混雜度到達了o(2^n),利用的記憶體空間也隨著函式呼叫棧的增長而增長。這顯明難受於實用的過程。else
}
2、表驅動的遞迴法。這裡不提單純的表驅動法,因為對於項數未知的fibonacci數列開啟***的空間來換取工夫未免不划算且不負責。我們只是為了肅清遞迴法中許多重複的計算,能夠將曾經計算過的其中值存入乙個表,已備後續利用:
#define max_log 20當n小於保留的表長時,由於每個其中值只計算順次,工夫混雜度降為o(n)。但隨著n的增大,要想堅持o(n)的工夫混雜度,就定然放大保留的表長,這就構成了儲存空間的浪費。static unsigned long logs[max_log] = ;
unsigned long fib(int n)
else if (n < max_log && logs[n] != 0) else
}
3、迭代法。求fibonacci數列第n項時固然要用到前面兩項的值,但它們僅作為臨時計算的其中值,不作為收穫輸出,因而無保留的必需,全面能夠改換成迭代法求解:
unsigned long fib(int n)迭代法的工夫混雜度為o(n),利用的記憶體空間也不會動態遞公升。個人感受fibonacci數列更輕便作為迭代法而非遞迴法的典例展目前教材上。else
return c;
}}
下面給出兩種數學性較強的演算法。琢磨到表白的簡明性,用matlab告終:
4、遷移矩陣法。此措施等閒見於線性代數中的markov過程示例。fibonacci數列第n項與第n-1項能夠穿越遷移矩陣的n-1次迭代求出:
**如下:
function y = fib(n)此演算法的工夫混雜度相當於計算矩陣乘方的工夫混雜度。在計算2階矩陣n次方時,萬一直接按矩陣乘法定義式展開,不加尤其優化,那工夫混雜度為o(n)。first = [1; 0];
trans = [1 1; 1 0];
last = trans ^ (n - 1) * first;
y = last(1, 1);
end
5、通項公式法。fibonacci數列的通項公式如下(驗證略):
利用通項公式能夠獲得fibonacci數列的任何項:
function y = fib(n)該措施的工夫混雜度傳神為o(1),但我們還該當琢磨乘方計算的工夫花費。不加尤其優化時,用乘法告終n次乘方的工夫混雜度為o(n)。琢磨到浮點數計算效率和精度問題,此措施在計算機告終時不及遷移矩陣法。sr5 = sqrt(5);
y = uint32((((1 + sr5) / 2) ^ n - ((1 - sr5) / 2) ^ n) / sr5);
end
下面再給出兩種對計算機告終有尤其含義,但同時有定然侷限性的告終措施(只是告終措施,不能稱為新的演算法)。其中利用了一些c++程式設計技巧,對利用其它語言告終也有定然的參看價值:
6、模板元程式設計法。等閒我們在c++中利用模板,僅限於類模板與函式模板。事實上c++扶持模板元程式設計,理論上能夠在編譯時厲行任何計算(甚至包括抉擇、迴圈、遞迴等構造)。**如下:
#define fib(n) fibt::val我們用乙個構造體作為模板的載體,用乙個列舉值保留計算收穫。其中第乙個模板為大約遞迴過程(利用遞迴演算法是為打聽釋的輕便,全面能夠用其它算***換,以加速編譯過程),後兩個模板為n=0、1時的模板特化。穿越#define語句將模板呼叫簡寫成相仿函式呼叫的措施。過程在編譯時計算所需的fibonacci數列項,將收穫作為常量嵌入編譯好的過程。執行時直接利用收穫,工夫混雜度懇摯地變成了o(1)。但這一措施最大的侷限即便只能對常量嵌入,過程中揭示諸如計算fib(i++)的情形則無能為力。儘管如此,這比在**中手工計算並寫入所需的值要直觀準確,比穿越單純的表驅動法「空間換時間」要得體迅捷。templatestruct fibt;};
template<> struct fibt<0>;};
template<> struct fibt<1>
;};
7、函式物件法。此措施重要用於c++ stl程式設計的通用演算法方面,其厲行行動也有別於以上其它措施:
class fib這個函式類物件的行動能夠會意為乙個「fibonacci數列發生器」,其測驗性呼叫如下,過程將順次列印unsigned long operator()()
else
}private:
int a, b, n;
};
void test(int i)函式物件具有與函式指標相仿的行動,同時又能保留切身的一些屬性,因而常用於stl通用演算法程式設計。但針對個體的fibonacci數列項求值,靈便性不及等閒的措施。while (i--);
}
渴望讀者能夠從上面的演算法分析中見微知著,有所會意。
起源:參看材料:
1、bruce eckel,thinking in c++ volume 2: practicalprogramming,機械工業出版社,2006
2、william j. collins,data structures and the standard templatelibrary,機械工業出版社,2003
3、knott's surrey university,the home page for fibonacci numbers andthe goldensection,其中,重要的增長來自相仿印度這麼的新興市場,在這裡每天大約有1.1億份報紙被銷售一空。
計算Fibonacci數列
上機內容 用動態分配空間的方法計算fibonacci數列的前30項並儲存到動態分配的空間中 上機目的 學習fibonacci數列演算法 我的程式 includeusing namespace std void main int p new int 30 p 1 p 1 1 cout p p 2 fo...
Fibonacci數列 餘數
fibonacci數列的遞推公式為 fn fn 1 fn 2,其中f1 f2 1。當n比較大時,fn也非常大,現在我們想知道,fn除以10007的餘數是多少。輸入格式 輸入包含乙個整數n。輸出格式 輸出一行,包含乙個整數,表示fn除以10007的餘數。說明 在本題中,答案是要求fn除以10007的餘...
Fibonacci數列求解
問題描述 fibonacci數列的遞推公式為 fn fn 1 fn 2,其中f1 f2 1。當n比較大時,fn也非常大,現在我們想知道,fn除以10007的餘數是多少。輸入格式 輸入包含乙個整數n。輸出格式 輸出一行,包含乙個整數,表示fn除以10007的餘數。說明 在本題中,答案是要求fn除以10...