演算法學習-第0篇 從Fibonacci開始,第0篇fibonacci
學習資源《Algorithms》,作者S.Dasgupta,C.H.Papadimitriou,and U.V.Vazirani。
電子版可到資產庫中下載http://download.csdn.net/detail/segen_jaa/7900765。
1、問題描述
Fibonacci數列想必大家都比較熟悉,後一位元字是前兩位的和。
0,1,1,2,3,5,8,13,21,34
對應公式如下。
求第n位的Fibonacci數為多少?
2、迭代演算法
實現語言:C語言。
win32程式下,計算Fibonacci數。
45位:1134903170
46位:1836311903
47位:-1323752223
計算到第47位long型已經不支援,故測試程式約定在50位以內。
#include "stdafx.h"#define MAX_NUM 50long fib1(int n){if (0 == n) return 0;if (1 == n) return 1;return fib1(n-1)+fib1(n-2);}int _tmain(int argc, _TCHAR* argv[]){while(true){int input = 0;printf("please input fibonacci number:");scanf("%d", &input);if (input>MAX_NUM){printf("please input number less than %d", MAX_NUM);continue;}if (input<0){break;}int result1 = fib1(input);printf("fib1 result:%d\n", result1);}return 0;}
3、迭代演算法分析
三個問題
①演算法是否正確?
②演算法複雜度多少?
③演算法能否改進?
對應回答:
①實現完全按照定義公式,正確性沒有疑問。
②看到遞迴,大家應該都知道了,這個演算法時間複雜度有點高。
一次加減操作複雜度都為1,那麼T(n)=T(n-1)+T(n-2)+3。
經過計算T(n)值≈
出現指數計演算法,那麼這個演算法可以宣告失敗了。這意味著電腦效能每提高1.6倍,只往前多計算出一位。
在這種演算法下,大家可以在自己機器上試一下計算要多久。本機cpu i7測試,推算第50位接近1小時時間。如果要同樣時間計算出第51位,只能等到i8、i9了。
③若要對演算法進行改進,則首先分析為何複雜度如此高。
遞迴調用的過程如下。
可以看到同一個數被重複計算了多次。以F(n-3)為例,在中被計算了三次。那麼我們的改進思路就從這裡入手,已計算過的數字就緩衝起來。
4、改進演算法
#include "stdafx.h"#define MAX_NUM 50long fib2(int n){long array[MAX_NUM];array[0] = 0;array[1] = 1;for (int i=2; i<=n; ++i){array[i] = array[i-1]+array[i-2];}return array[n];}int _tmain(int argc, _TCHAR* argv[]){while(true){int input = 0;printf("please input fibonacci number:");scanf("%d", &input);if (input>MAX_NUM){printf("please input number less than %d", MAX_NUM);continue;}if (input<0){break;}int result2 = fib2(input);printf("fib2 result:%d\n", result2);}return 0;}
同樣的問題
①演算法是否正確?
答:正確。
②演算法複雜度多少?
答:複雜度O(n)。
③演算法能否改進?
答:效能已為線性,可不再改進。
斐波那契數列的演算法
#include<stdio.h>
void Fdt(long F1,long F2,int N);//遞推
void Fdg(long F1,long F2,int N);//遞迴
main()
{
int n=20;
long f1,f2;
f1=f2=1;
Fdt(f1,f2,n);
printf("\n\n");
Fdg(f1,f2,n);
}
void Fdt(long F1,long F2,int N)//遞推
{
for(int i=1;i<=N;i++)
{
printf("%12ld %12ld",F1,F2);
if(i%2==0)
printf("\n");
F1=F1+F2;
F2=F1+F2;
}
}
void Fdg(long F1,long F2,int N)//遞迴
{
if(N>=1)
{
printf("%12ld %12ld",F1,F2);
if(N%2==0)
printf("\n");
Fdg(F1+F2,F1+F2+F2,N-1);
}
}
[C語言]用遞迴演算法編寫一個程式Fibonacci數列的第n項值
#include <stdio.h>
unsigned int Fibonacci(int n);
int main( void )
{
int i;
for(i = 1 ;i <= 20;i ++)
{
printf("%d\n",Fibonacci(i));
}
return 0;
}
unsigned int Fibonacci(int n)
{
if( n == 1 || n == 2) // 遞迴結束的條件,求前兩項
return 1;
else
return Fibonacci(n-1)+Fibonacci(n-2); // 如果是求其它項,先要求出它前面兩項,然後做和。
}
這種演算法效率比較低
哪裡不清楚可以Hi我