第一章 绪论 之 递归
看完第一章后,相比于学校的课程,题主最递归的理解更加深入与透彻,接下来进行一些总结:
-
递归算法复杂度的分析方法有两个
递归跟踪
递推方程 -
递归的类型
线性递归 (比如:减而治之)
二分递归 (比如:分而治之) -
多递归基与多向递归
一个递归算法可以设置多个递归基,但多向递归的返回情况只能从中选取一个,而不是全部,这样就能够保证线性递归,判断是不是线性递归就看递归的分支是不是每次只能选一个 -
Fibonacci 数算法的三种递归方式(对应习题【1-21】)
a. 二分递归版 O( log n )
b. 线性递归版 O( n )
c. 迭代版 O( 2n )
#include<iostream>
#include<cmath>
#include<time.h>
//题主不会使用C++的精确时间戳,还请海涵
//最终跑出来的结果只能看出迭代版和线性递归的明显区别,而不能看出线性递归和二分递归的区别
using namespace std;
struct metrix { //定义2*2矩阵结构体
int lu, ld, ru, rd; //l:left r:right u:up d:down
metrix(int x, int y, int z, int w) :lu(x), ld(y), ru(z), rd(w) {}
metrix operator * (metrix y) { //重载*作为矩阵乘法运算符
return metrix{ lu * y.lu + ru * y.ld,ld * y.lu + rd * y.ld,lu * y.ru + ru * y.rd,ld * y.ru + rd * y.rd };
}
metrix power(int n ) { //矩阵乘幂函数,这是迭代版能达到O( log n )的核心
if (n == 1) return *this;
if (n & 1) return this->power(n / 2) * this->power(n / 2) * metrix(*this);
else return this->power(n / 2) * this->power(n / 2);
}
};
__int64 fib_iterate(__int64 x) { //迭代版递归O( log n )
if (x < 2) return x;
return fib_iterate(x - 1) + fib_iterate(x - 2);
}
__int64 fib_liner(int x, __int64 &prev) { //线性递归O( n ),递归实例呈线性
if (x == 1) {
prev = 0;
return prev + 1;
}
__int64 prePreval;
prev = fib_liner(x - 1, prePreval);//核心在于通过引用的方式给主调函数fib( n )传递fib( n-2 ),通过return形式传递fib( n-1 )
return prev + prePreval;
}
__int64 fib_binary(int x) { //O( 2^n )最容易想到的二分递归,递归实例呈现树状
if (x == 0) return 0;
metrix m = metrix{ 0,1,1,1 }.power(x);
return m.ru;
}
int main() {
int n;
cout << "Please input the base of fabonacci :";
cin >> n;
__int64 pre;
time_t tv1, tv2, tv3, tv4;
tv1 = time(NULL);
cout << "fib_iterate( " << n << " ) = " << fib_iterate(n) << endl;
tv2 = time(NULL);
cout << "fib_liner( " << n << " ,pre ) = " << fib_liner(n, pre) << endl;
tv3 = time(NULL);
cout << "fib_binary( " << n << ") = " << fib_binary(n) << endl;
tv4 = time(NULL);
cout << "Iterate: " << tv2 - tv1 << endl;
cout << "Liner : " << tv3 - tv2 << endl;
cout << "Binary : " << tv4 - tv3 << endl;
}
以下是我的运行结果,计算 fib( 42 ) 的时间效率比较