のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

C++で書くフィボナッチ数列

Sponsored Links

皆さんこんにちは
お元気ですか

たまには面白くフィボナッチ数列をC++で解いてみようかなと思います。

フィボナッチ数列って?

{ \displaystyle
F_n = F_{n-1} + F_{n-2}
}

0 1 2 3 5 8 13・・・・・・・となるような結構有名な数列です。
今回3通りの解き方で解いてみたよ

再帰

非常に遅くて有名な再帰です。求めたい値を放り込み、再帰的に計算させていきます。

class RecursiveFibonacci:public Fibonacci{
public:
	virtual int calc(int x);
};

int RecursiveFibonacci::calc(int x){
	if(x == 0){
		return 0;
	}else if(x == 1){
		return 1;
	}else{
		return calc(x - 1) + calc(x - 2);
	}
}

メモ化再帰

再帰ですが、一度求めたものは計算させず、配列に保存した値を返す。O(N)

class MemorizeFibonacci:public Fibonacci{
	int memo[10000] = {0};
public:
	virtual int calc(int x);
};

int MemorizeFibonacci::calc(int x){
	if(x == 0){
		return 0;
	}else if(x == 1){
		return 1;
	}else if(memo[x] != 0){
		return memo[x];
	}
	memo[x] = calc(x-1) + calc(x-2);
}

動的計画法

メモ化再帰と違う点は初めから順番に行う操作(計算)を行う点ですね。O(N)

class DPFibonacci:public Fibonacci{
public:
	virtual int calc(int x);
};

int DPFibonacci::calc(int x){
	int dp[1000] = {0};
	dp[0] = 0;
	dp[1] = 1;
	for(int i = 2; i < x; i++){
		dp[i] = dp[i-1] + dp[i-2];
	}
	return dp[x];
}

因みに50で時間を比較すると全く違います。
再帰で行うシステムはn = 50で165秒かかります。
ほかはほとんどかかりませんが・・・・

ソースコード全て

#include <iostream>
#include <vector>

using namespace std;

class Fibonacci{
public:
	virtual int calc(int x) = 0;	
};

class RecursiveFibonacci:public Fibonacci{
public:
	virtual int calc(int x);
};

int RecursiveFibonacci::calc(int x){
	if(x == 0){
		return 0;
	}else if(x == 1){
		return 1;
	}else{
		return calc(x - 1) + calc(x - 2);
	}
}

class MemorizeFibonacci:public Fibonacci{
	int memo[10000] = {0};
public:
	virtual int calc(int x);
};

int MemorizeFibonacci::calc(int x){
	if(x == 0){
		return 0;
	}else if(x == 1){
		return 1;
	}else if(memo[x] != 0){
		return memo[x];
	}
	memo[x] = calc(x-1) + calc(x-2);
}

class DPFibonacci:public Fibonacci{
public:
	virtual int calc(int x);
};

int DPFibonacci::calc(int x){
	int dp[1000] = {0};
	dp[0] = 0;
	dp[1] = 1;
	for(int i = 2; i < x; i++){
		dp[i] = dp[i-1] + dp[i-2];
	}
	return dp[x];
}

class TimeFibonatti{
public:
	Fibonacci *t_fib;
	void setFibonacci(Fibonacci *fib){
		t_fib = fib;
	}

	void calcTime(int x){
		clock_t start = clock();
		t_fib->calc(x);
		cout << (double)(clock() - start) / CLOCKS_PER_SEC << endl;
	}
};

int main(int argc, char const *argv[]){
	Fibonacci *r_fib = new RecursiveFibonacci();
	Fibonacci *m_fib = new MemorizeFibonacci();
	Fibonacci *dp_fib = new DPFibonacci();

	TimeFibonatti *t_fib = new TimeFibonatti();
	vector<Fibonacci*> fib(3);
	fib[0] = r_fib;fib[1] = m_fib;fib[2] = dp_fib;

	for(int i = 0; i < fib.size(); i++){
		t_fib->setFibonacci(fib[i]);
		t_fib->calcTime(50);
	}
	return 0;
}